大前端 - vue - Vue-Router 原理实现 - history模式
Hash 模式和 History 模式的区别2种方式都是客户端路由的实现方式,也就是当路径发生变化,不会向服务器发生请求。使用js监视路径的变化,不同的地址渲染不同的内容,如果需要服务端内容发送ajax。表现形式的区别:Hash:携带#,#之后是路由地址,可以通过?携带参数。很丑。 https://music.163.com/#/paylist?id=3102977778History: 一个正常
Hash 模式和 History 模式的区别
2种方式都是客户端路由的实现方式,也就是当路径发生变化,不会向服务器发生请求。使用js监视路径的变化,不同的地址渲染不同的内容,如果需要服务端内容发送ajax。
- 表现形式的区别:
Hash:携带#,#之后是路由地址,可以通过?携带参数。很丑。 https://music.163.com/#/paylist?id=3102977778
History: 一个正常的url. https://music.163.com/paylist/3102977778.
- 原理的区别:
Hash:模式是基于锚点,以及onhashchange事件。通过锚点的值作为路由地址,当地址发生变化后,触发onhashchange事件。根据路径决定页面的内容。
History:模式是基于html5中的History api
1. history.pushState(). IE10以后才支持 。
2. history.replaceState()
pushState和push方法的区别是:当我们调用history.push方法时,路径会发生变化,这个时候要向服务器发送请求,而我们调用history.pushState时,不会向服务器发送请求,只会改变我们浏览器中地址栏中的地址,并且把我们的地址就录到历史路径中,因此通过history.pushState可以实现客户端路由,但是 history.pushState(). IE10以后才支持,也就是使用history有兼容性问题。
-
History 模式 - Node.js
-
History 模式 - nginx
默认80端口
启动:start nginx
重启:nginx -s reload
停止:nginx -s stop
html: 用来存储网站。打包好的前端代码,放到html文件夹中,替换默认的index.html为最新的。
nginx端口:默认是80端口,如果80端口被占用,无法启动,也不会报错。
验证nginx启动是否成功:在浏览器中输入:localhost回车:
显示如下:则启动成功。
nginx.conf
server {
# 静态资源根路径变量
set $root /home/admin;
listen 8080; // 监听的端口,默认是80端口,如果80端口被占用,可以重新设置
server_name localhost; // 绑定的域名,默认是localhost,指的是本地
charset utf-8;
# 静态资源根路径,(后面相关前端静态资源都放单该路径下)
root /home/admin;
# 在location中指定了当前网站的根目录,root :默认的根目录,index: 默认的首页,也就是当我们访问localhost按回车的时候,在根目录中找index.html,或者index.htm
location / {
try_files $uri $uri/ @router; // try_files:配置vue-route histroy模式:try_files:表示试着访问,$uri:当前请求的路径,会找这个路径对应的文件,如果找到就把这个路径返回,如果找不到接着找$uri/,$uri/表示文件目录,找这个$uri/下面的首页,index.html,indx.htm,如果找到返回,找不到继续匹配
index index.html index.htm;
}
location @router {
rewrite ^.*$ /index.html last;
}
location /api {
// 配置的反向代理
proxy_pass http://backend;
}
location /innerapi {
proxy_pass http://backend;
}
}
2vue-router实现原理
使用到的知识库:
history模式:
- 插件
- 混入
- Vue.observable()
- 插槽
- render函数
- 运行时和完整版的Vue
vue-router实现原理:vue-router是前端路由,当路径切换的时候浏览器判断当前路径并加载当前路径对应的组件
hash模式:是把url中#后面的内容作为路径地址,直接可以通过location.url来切换浏览器中的地址,如果只改变了路径中#后面的内容,浏览器不会向服务器请求这个地址,但是会把这个地址记录到浏览器的访问历史中,当hash改变后,我们需要监听hash的变化,并做相应的处理,我们只需要监听hashchange事件,当hash发生变化后,触发hashchange事件,在hashchange事件中记录当前的路由地址,并找到该路径对应的组件,然后重新渲染。
history模式:就是一个普通的url,通过使用history.pushState()方法改变浏览器的地址栏, 注意:pushState方法仅仅是改变地址栏,并把当前地址记录到浏览器的访问历史中,并不会真正的跳转到指定的路径,也就是浏览器不会向服务器发送请求。通过监听popstate事件,可以监听到浏览器历史操作的变化。 在popstate事件的处理函数中,可以记录改变后的地址。要注意的是:当调用的是pushState,或者是replacestate的时候,并不会触发该事件,当点击浏览器的前进和后退按钮的时候,或者调用history.back,history.forword方法时,该事件才会触发,最后当地址改变之后,要根据当前的地址,找到对应的组件,进行重新渲染。
2.3实现自己的vue-router history模式
回顾核心代码:
类图:用来描述类中的所有成员。
类属性:
option:记录构造函数中传递的对象
data:是一个对象,当中有一个属性current,用来记录当前的路由地址。我们需要一个响应式的对象,data就是一个响应式的对象。因为地址发生变化,组件也要自动改变,我们使用Vue.observable()这个方法。
routeMap:是一个对象记录:路由地址和组件的对应关系。
类方法:
+ 对外公开的方法
- 静态方法
_install:静态方法:用来实现vue的插件机制。
inti:调用下面的3个方法
initEvent: 用来注册popState事件,监听浏览器历史的变化。
createRouteMap:初始化routeMap,把我们传递过来的路由规则转化为键值对的形式存储到routeMap对象中。键:路由地址; 值:对应的组件。
initCompoents:创建route-link,route-view组件。
2.4 VueRouter-install
-
运行时版本:
不支持template模版,需要打包的时候提前编译。 -
完整版本:
包含运行时和编译器,体积比运行时版大10k左右,程序运行的时候把模版转换成render函数。
Vue-Router.js
console.dir(Vue)
let _Vue = null
class VueRouter {
static install(Vue){
//1 判断当前插件是否被安装
//2 把Vue的构造函数记录在全局
//3 把创建Vue的实例传入的router对象注入到Vue实例
//1 判断当前插件是否被安装
if(VueRouter.install.installed){
return; // 如果已经安装直接return
}
VueRouter.install.installed = true // 插件已经被安装
//2 把Vue的构造函数记录在全局
_Vue = Vue
//3 把创建Vue的实例传入的router对象注入到Vue实例
// _Vue.prototype.$router = this.$options.router
_Vue.mixin({
beforeCreate(){
if(this.$options.router){
_Vue.prototype.$router = this.$options.router
}
}
})
}
constructor(options){
this.options = options
this.routeMap = {}
// observable
this.data = _Vue.observable({
current:"/"
})
this.init()
}
init(){
this.createRouteMap()
this.initComponent(_Vue)
this.initEvent()
}
createRouteMap(){
//遍历所有的路由规则 把路由规则解析成键值对的形式存储到routeMap中
this.options.routes.forEach(route => {
this.routeMap[route.path] = route.component
});
}
initComponent(Vue){
// 创建router-link组件
Vue.component("router-link",{
props:{
to:String
},
render(h){
return h("a",{
attrs:{
href:this.to
},
on:{
click:this.clickhander
}
},[this.$slots.default])
},
methods:{
clickhander(e){
history.pushState({},"",this.to)
this.$router.data.current=this.to
e.preventDefault()
}
}
// 第2种创建组件的方法:运行时版本:
// template:"<a :href='to'><slot></slot><>"
})
const self = this
// 创建router-view组件
Vue.component("router-view",{
render(h){
// self.data.current
const cm=self.routeMap[self.data.current]
return h(cm)
}
})
}
initEvent(){
//
window.addEventListener("popstate",()=>{
this.data.current = window.location.pathname
})
}
}
更多推荐
所有评论(0)