共计 2326 个字符,预计需要花费 6 分钟才能阅读完成。
Hash 和 History 模式
Hash 模式
http://localhost.com/#/user/id
Hash 模式基于锚点,以及 onhashchange 事件。
- 通过
window.location.href
改变浏览器地址,如果只扭转#
前面的地址,不会触发服务端申请,会把#
后的值作为路由地址 - 当地址发生变化时触发
onhashchange
事件,监听事件并做相应解决 - 切换显示不同的组件
History 模式
http://localhost.com/user/id
History 模式基于 HTML5 中的 History API
-
通过 history.pushState() 办法扭转浏览器地址,只会扭转浏览器地址而不会向服务端发送申请,并把以后地址记录到浏览器的历史记录中
- history.pushState():不会向服务端发送申请,pushState 会在 history 栈中增加一个新的记录
- history.replaceState():不会向服务端发送申请,replaceState 不会增加新的 history 栈记录,而是替换以后的 url
- 监听 popstate 事件,能够监听到浏览器历史数据的变动。事件不会在 pushStash 或 replaceStash 中触发,只会在浏览器后退或回退时触发
- 依据以后路由地址找到对应组件从新渲染
nginx 环境配置
location / { root html; | |
index index.html index.htm; #新增加内容 | |
#尝试读取 $uri(以后申请的门路),如果读取不到读取 $uri/ 这个文件夹下的首页 | |
#如果都获取不到返回根目录中的 index.html try_files $uri $uri/ /index.html; | |
} |
模仿实现
-
创立 VueRouter 插件,静态方法 install
- 判断插件是否曾经被加载
- 当 Vue 加载的时候把传入的 router 对象挂载到 Vue 实列上(全局混入的目标是拿到 Vue 实列)
-
创立 VueRouter 类
- 初始化,options、routeMap、data(门路,创立 Vue 实例作为响应式数据记录以后门路)
- createRouteMap() 遍历所有路由信息,把组件和路由的映射记录到 routeMap 对象中
- initComponent() 创立 router-link 和 router-view 组件
- initEvent() 注册 popstate 事件,当路由地址发生变化,从新记录以后的门路
- 当门路扭转的时候通过以后门路在 routerMap 对象中找到对应的组件,渲染 router-view
let _Vue = null; | |
export default class VueRouter {constructor(options) { | |
this.options = options; | |
this.routeMap = {}; | |
this.data = _Vue.observable({current: "/",}); | |
this.createRouteMap(); | |
this.initComponent(_Vue); | |
this.initEvent();} | |
static install(Vue) { | |
//1 判断以后插件是否被装置 | |
if (VueRouter.install.installed) {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;} | |
}, | |
}); | |
} | |
// 遍历所有的路由规定 吧路由规定解析成键值对的模式存储到 routeMap 中 | |
createRouteMap() {this.options.routes.forEach((route) => {this.routeMap[route.path] = route.component; | |
}); | |
} | |
// 创立 router-link 和 router-view 组件 | |
initComponent(Vue) { | |
Vue.component("router-link", { | |
props: {to: String,}, | |
render(h) { | |
return h( | |
"a", | |
{ | |
attrs: {href: this.to,}, | |
on: {click: this.clickHandler,}, | |
}, | |
[this.$slots.default] | |
); | |
}, | |
methods: {clickHandler(e) { | |
// 扭转地址,不发送申请,记录地址历史 | |
history.pushState({}, "", this.to); | |
this.$router.data.current = this.to; | |
// 阻住后续执行,不让超链接跳转 | |
e.preventDefault();}, | |
}, | |
// template:"<a :href='to'><slot></slot><>" | |
}); | |
const self = this; | |
Vue.component("router-view", {render(h) {const cm = self.routeMap[self.data.current]; | |
return h(cm); | |
}, | |
}); | |
} | |
// 注册 popstate 事件,当路由地址发生变化,从新记录以后的门路 | |
initEvent() {window.addEventListener("popstate", () => {this.data.current = window.location.pathname;}); | |
} | |
} |
正文完