Vito's blog
  • js基础
  • es6+基础
  • js进阶
  • js手写系列
  • typescript
  • js读书笔记

    • js异步编程
    • 你不知道的js系列
  • vue2基础
  • vue2进阶
  • vue3基础
  • vuex
  • vue router
  • pinia
html
  • 图解css3
  • css进阶
  • scss
浏览器
网络通信
  • git使用笔记
  • linux使用记录
  • npm
  • webpack基础
  • webpack5
  • qiankun
  • 排序算法
  • 剑指offer
  • 常见算法
  • 排序算法python
  • 剑指offer-python
  • labuladong算法
github主页
  • js基础
  • es6+基础
  • js进阶
  • js手写系列
  • typescript
  • js读书笔记

    • js异步编程
    • 你不知道的js系列
  • vue2基础
  • vue2进阶
  • vue3基础
  • vuex
  • vue router
  • pinia
html
  • 图解css3
  • css进阶
  • scss
浏览器
网络通信
  • git使用笔记
  • linux使用记录
  • npm
  • webpack基础
  • webpack5
  • qiankun
  • 排序算法
  • 剑指offer
  • 常见算法
  • 排序算法python
  • 剑指offer-python
  • labuladong算法
github主页
  • vueRouter从基础到原理

vueRouter从基础到原理

基本概念

vue-router封装了一个全局混入,定义了两个挂载在原型上的变量,注册了两个组件;
支持三种路由方式:hash, history, abstract
提供两种组件:<router-link>、 <router-view>
定义两个变量:$router, $route
暴露了一系列实例方法和钩子函数
vue-router 3.. 版本项目地址

路由导航解析流程:

  1. 导航被触发。
  2. 在失活的组件里调用离开守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。

基础使用

详细使用方法见:官方文档

  • 路由的绑定与vuex类似
// router/index.js  
import VueRouter from 'vue-router'  
import MyComponent from '../component/MyComponent' // 引入自定义组件  
export default new VueRouter({  
  routes:[  
    {path:'/myComponent', component: MyComponent}, // 配置项  
    {  
      path: '/mutilRouter',  
      name:'namedRouter', // 命名路由  
      components: {default:MyComponent1, a:MyComponent2}, // 对应命名视图  
      children:[ // 多级路由children配置与routes类似  
        {path:'child1', component:child1} // 子路由中可省略根路径'/'字符  
        {path:'child2/:arg1/:arg2', component:child2} // 配置:arg1占位表示params方式路由传参  
      ]  
    }  
  ]  
})  
// main.js  
import VueRouter from 'vue-router'  
import router from './router'  
Vue.use(VueRouter)  
new Vue({  
  router:router,  
  ... // 此处省略了其他配置项  
})  
  • 路由的使用
<!-- 导航组件中 -->  
<router-link to="/myComponent">我的组件</router-link> <!-- 最终会被编译为<a>标签 -->  
<router-link to="/mutilRouter/child1">子组件中的多级路由</router-link>  
<!-- 导航组件中内容展示区占位 -->  
<router-view>路由占位符/多级路由也适用</router-view>  
<router-view name="a">命名视图占位符</router-view>  
  
<!-- 路由传参 -->  
<router-link :to="`/mutilRouter/child1?arg1=${this.arg1}&arg2=${this.arg2}`">拼字符串的形式传递路由query参数</router-link>  
<router-link :to="`/mutilRouter/child2/${this.arg1}/${this.arg2}`">拼字符串的形式传递路由params参数</router-link>  
<router-link :to="{  
  path:'/mutilRouter/child1',  
  // name:namedRouter, // 若定义了命名路由可直接写name不用写path属性  
  query:{arg1:this.arg1, arg2:this.arg2},  
  // params:{arg1:this.arg1, arg2:this.arg2} //params方式传参  
}">传对象形式传递路由query参数</router-link>  
<!-- 被路由的组件中 -->  
<div>{{$route.query.arg1}}</div>  

路由配置中可传递固定参数props,子组件中能够通过props属性访问到对应的参数

  • 路由方式与编程式路由导航

默认路由方式为push模式,url访问历史以push的方式记录,设置标签replace属性:<router-link replace>该路由模式改为replace模式,新的url访问历史将不断替换上一条记录

this.$router.push(Object) // Object参数与标签中to参数类似  
this.$router.replace(Object) // 以replace模式路由  
this.$router.back() // 后退  
this.$router.forward() // 前进  
this.$router.go(n) // 前进或后退n条记录  
  • 在路由中使用keep-alive

通过vue内置组件keep-alive可以缓存路由组件,以便进行快速路由切换.被缓存的组件中定时器等回调不会停止运行

<keep-alive include="要缓存的路由组件名">  
<!-- <keep-alive :include="['组件1', '组件2']"> -->  
  <router-view></router-view>  
</keep-alive>  
<!-- 若跳转至其上级路由,由于父组件被销毁,因此子组件也会被销毁 -->  

被keep-alive的组件中独有的两个生命周期函数

activated(){  
  // 被路由展示时触发  
  // 在此函数中启动激活交互所需的事件/定时器  
}  
deactivated() {  
  // 路由切走,组件被缓存时触发  
  // 在此事件中停止失活后不需要的事件/定时器  
}  
  • 路由守卫
// 全局路由守卫,初始化及每次路由切换之前被调用  
router.beforeEach((to, from, next) => {  
  // to 要路由到的目标route  
  // from 发起跳转的来源  
  // next回调函数,调用对该路由请求放行  
})  
// 后置路由守卫,初始化及每次路由切换后调用  
router.afterEach((to, from) => {  
})  
// 独享路由守卫,通过beforeEnter属性添加到routes配置对应的路由中  
{  
  name:'要守卫的路由', path:'/before', component: Home,  
  beforeEnter: (to, from, next) => {  
    // 仅该路由及其子路由会被拦截  
  }  
}  
// 组件内路由守卫路由规则卸载组件内,与生命周期函数平级  
{  
  mounted(){},  
  beforeRouteEnter(to, from, next) {  
    // 通过路由规则进入该组件时被调用  
  }  
  beforeRouteLeave(to, from, next) {  
    // 通过路由规则离开该组件时被调用  
  }  
}  

原理

history 模式依赖于 window.history.pushState(),replaceState()等api完成跳转而无需重新加载页面 TODO

源码核心简读

手写实现

Last Updated: 10/11/22, 9:52 PM
Contributors: vito