共计 3766 个字符,预计需要花费 10 分钟才能阅读完成。
Vue-Router 的两种模式思路
Hash 模式
- 1、hash 即 URL 中 #前面的局部。
- 2、如果网页 URL 带有 hash,页面会定位到 id 与 hash 一样的元素的地位,即锚点
- 3、hash 的扭转时,页面不会从新加载,会触发 hashchange 事件,而且也会被记录到浏览器的历史记录中
- 4、vue-router 的 hash 模式,次要就是通过监听 hashchange 事件,依据 hash 值找到对应的组件进行渲染(源码里会先判断浏览器支不反对 popstate 事件,如果反对,则是通过监听 popstate 事件,如果不反对,则监听 hashchange 事件)
History 模式
- 1、通过 history.pushState 批改页面地址
- 2、当 history 扭转时会触发 popstate 事件,所以能够通过监听 popstate 事件获取路由地址
- 3、依据路由地址找到对应组件进行渲染
vue-router 应用
1、注册 vue-router 插件
import VueRouter from 'vue-router'
// 注册 VueRouter 插件
// Vue.use 办法
// 1、如果传入的是办法,则调用传入的办法
// 2、如果传入的是对象,则会调用插件的 install 静态方法,并传入 Vue 构造函数
Vue.use(VueRouter)
2、创立 Router 实例
// 创立路由表
const routes = [
{
path: '/home',
component: Home,
},
{
path: '/about',
component: About,
},
]
// 实例化路由对象
const router = new VueRouter({
mode: 'hash',
routes
})
3、Vue 实例上挂载 router 实例
// 实例化 Vue 时,在实例上注册 router 对象
new Vue({render: h => h(App),
router
}).$mount('#app')
组件中应用
<router-view></router-view>
<router-link to="/home"><route-link>
// 通过 this.$router 获取路由对象
总结,VueRouter 须要做以下这些事件
- 1、实现 install 静态方法
- 2、依据传入的路由配置,生成对应的路由映射
- 3、给 Vue 实例挂载 router 实例
- 4、注册全局组件 <router-view> 和 <router-link>, router-view 组件通过以后 url 找到对应组件进行渲染,并且 url 扭转时,从新渲染组件,router-link 则渲染为 a 标签
- 5、通过 currentUrl 变量保留以后 url,并使数据变为响应式
- 6、监听 hashchange 或 popState 事件,浏览器记录扭转时从新渲染 router-view 组件
代码实现
let VueConstructor = null
export default class MyVueRouter {static install(Vue) {
/*
1、保留 Vue 构造函数
2、在 Vue 实例挂载 $router 实例
3、注册全局组件 <router-view></router-view> 和 <router-link>
*/
// 判断是否曾经执行过 install
if(MyVueRouter.installed) {return}
MyVueRouter.installed = true
// 1 保留 Vue 构造函数
VueConstructor = Vue
// 2、通过全局混入的形式,在 Vue 实例挂载 $router 实例
// install 执行的时候,Vue 还没有实例化,所以通过 mixin。在 Vue 实例化时去挂载 router
// 因为是全局混入,要判断是不是根实例,才须要挂载 router
Vue.mixin({beforeCreate() {
// 只有根实例 才须要挂载 $router, 组件不须要执行
if (this.$options.router) {// new Vue(options) 时,曾经把 router 对象保留到 $options 里,所以能够通过 $options.router 获取
console.log('this.$options.router==', this.$options.router)
Vue.prototype.$router = this.$options.router
}
},
})
// 3、注册全局组件 <router-view></router-view> 和 <router-link>
// <router-link to="/home"></router-link>
Vue.component('router-link', {
props: {
to: {
type: String,
required: true,
},
},
methods: {clickHandler(e) {if (this.$router.$options.mode === 'history') {
// history 通过 pushState 扭转地址,阻止默认行为
console.log('history 模式')
history.pushState({}, '', this.to)
this.$router._data.currentUrl = this.to
e.preventDefault && e.preventDefault()}
}
},
render(h) {
return h(
'a',
{
attrs: {href: '#' + this.to,},
on: {click: this.clickHandler}
},
this.$slots.default
)
},
})
Vue.component('router-view', {render(h) {const { routesMap, _data} = this.$router
const component = routesMap[_data.currentUrl]
console.log('component==', component)
return h(component)
},
})
}
constructor(options) {
/*
1、保留配置选项
2、获取路由映射,能够通过 hash 获取到对应组件
3、设置响应式变量 currentUrl,保留以后 url
4、监听 hashchange 事件,hash 扭转时,同时扭转 currentUrl
*/
// 1、保留配置选项
this.$options = options
// 2、获取路由映射,能够通过 hash 获取到对应组件
this.routesMap = {}
this.$options.routes.forEach((route) => {this.routesMap[route.path] = route.component
})
console.log('routesMap===', this.routesMap)
// 3、设置响应式变量 currentUrl,保留以后 url
this._data = VueConstructor.observable({currentUrl: '/',})
// 4、监听 popstate 或 hashchange 事件,hash 扭转时,同时扭转 currentUrl
// 如果浏览器反对 popstate,则监听 popstate,不反对应用 hashchange
window.addEventListener('hashchange', () => {this._data.currentUrl = window.location.hash.slice(1)
console.log('this.currentUrl==', this._data.currentUrl)
})
}
}
源码实现思路
- 因为 Vue.use 办法会调用 install 静态方法,并传入 Vue 的构造函数,所以能够在 install 办法保留 Vue 构造函数,使 VueRouter 外部也能够应用到 Vue
- 通过 VueRouter.installed 判断插件是否曾经装置过,装置过的就无须要再次执行 install
- 通过 Vue.mixin 混入的形式,在 Vue 实例化时,在 beforeCreate 生命周期里,给 Vue 原型挂载 router 对象 Vue.prototype.$router = router,这里只须要挂载根实例,组件则不须要挂载,通过 $options.router 判断是否是根实例
- 注册 router-view、router-link 全局组件
- router-view, 依据以后 url 在路由表中找到对应组件,进行渲染。并且以后 url 扭转时,从新渲染。能够通过一响应式变量保留以后 url。
- router-link 渲染为 a 标签,如果是 history 模式,点击时通过 history.pushState 扭转浏览器记录,并阻止 a 标签默认行为,避免页面刷新
- 在 VueRouter 构造函数中,保留路由配置,并通过传入的路由表生成路由映射
- 通过变量 currentUrl 保留以后 url,并将 currentUrl 设置为 Vue 的响应式变量,让 Vue 帮忙做依赖收集,router-view 则通过依赖 currentUrl 去获取绝对应组件,这样 currentUrl 扭转时 route-view 会从新渲染
- 监听浏览器 popstate 事件,url 扭转时,currentUrl 从新设值(hash 模式如果浏览器不反对 popstate,则监听 hashchange)
正文完
发表至: javascript
2021-03-17