路由实现原理:
- 控制地址栏的改变
- 根据地址栏的改变来控制组件的切换
模式:
- hash路由(hashchange)
hash路由的关键在于:在router-link中,调用window.location.hash改变页面的hash值,然后在router-view中在window对象上监听hashchange事件。
router-link:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div> <span @click="jump"> <!-- 插槽显示组件调用时内部的内容 --> <slot></slot> </span> </div> </template> <script> export default { // 通过prop属性to,接受外面传进来的参数 props: ['to'], methods: { jump() { // 控制地址栏的改变 window.location.hash = this.to } } } </script>
router-view:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div> <!-- 动态组件 --> <component :is='componentId'></component> </div> </template> <script> import Recommend from '../components/Recommend' import Singer from '../components/Singer' import Rank from '../components/Rank' export default { data: () => ({ componentId: 'Recommend' }), components: { Recommend, Singer, Rank }, created () { // 模拟路由表 let routers = [ { path: '/recommend', component: 'Recommend' }, { path: '/singer', component: 'Singer' }, { path: '/rank', component: 'Rank' } ] window.addEventListener('hashchange', () => { // 监听hash值的改变并截取hash值 let hash = window.location.hash.split('#')[1] // 进行匹配 routers.map((item) => { if(item.path === hash){ this.componentId = item.component } }) }) } } </script>
- history路由(popState)
history路由的关键在于:H5 history新增了两个API: history.pushState和history.replaceState
两个api都接受3个参数
-
状态对象(state object):一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝。
-
标题(title):FireFox浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也可以传入一个简短的标题,标明将要进入的状态。
-
地址(URL): 新的历史记录条目的地址。浏览器不会在调用pushState()方法后加载该地址,但之后,可能会试图加载,例如用户重启浏览器。新的URL不一定是绝对路径;如果是相对路径,它将以当前URL为基准;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。该参数是可选的;不指定的话则为文档当前URL。
以及在router-view中监听popstate事件
当活动历史记录条目更改时,将触发popstate事件。
需要注意的是调用history.pushState()或history.replaceState()不会触发popstate事件,只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮。
router-link关键代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
jump() {
// 控制地址栏的改变
// window.location.hash = this.to
window.history.pushState(null,null, this.to)
// 需要注意的是调用history.pushState()或history.replaceState()不会触发popstate事件。只有在做出浏览器动作时,才会触发该事件,如用户点击浏览器的回退按钮(或者在Javascript代码中调用history.back())
}
router-view关键代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
window.addEventListener('popstate', () => {
// 监听hash值的改变并截取hash值
// console.log(window.history, window.location)
let history = window.location.pathname
console.log(history)
// 进行匹配
routers.map((item) => {
if(item.path === history){
this.componentId = item.component
}
})
})
其余代码与hash路由示例一样
当然这里只是简单的摊诉了路由的实现原理,如果要深入了解Vue的路由实现机制的可以查看vue的源码。