模拟 VueRouter 1

回顾 VueRouter 的核心代码

js 复制代码
Vue.use(VueRouter)
const router = new VueRouter({
  routes: [
    {name: 'home', path: '/', component: Home}
  ]
})
new Vue ({
  router,
  render: h => h(App)
}).$mount("#app')

分析

Vue.use(VueRouter)

这里使用了 Vue 的插件机制,Vue.use 接收一个函数或者对象,如果是一个方法则直接调用,如果是一个对象则调用其 install 方法。install 方法接收 2 个参数,一个是 Vue 的构造函数,一个是可选的选项对象(这里不做设置)。

所以从这句话来看,我们可以将 VueRouter 看做一个有 install 静态方法的类。

且 插件是仅需要注册一次的,在 js 中,方法本身就是一个对象,那我们不妨在 install 方法上添加一个属性表明此组件是否被注册过。

在注册 VueRouter 插件的时候会传入 Vue 的构造函数,这个 Vue 在其他地方肯定还会用到,所以先将其存入到全局变量中。

js 复制代码
let _Vue = null
class VueRouter {
  static install (Vue) {
    // 判断当前插件是否已经被安装
    if (VueRouter.install.installed) return 
    VueRouter.install.installed = true
  }
  // 把 Vue 构造函数记录到全局变量中
  _Vue = Vue
}

new Vue ({ router )}

创建 Vue 根实例 的时候传入 router 选项,会往所有 Vue 实例上添加 $route$router 属性。

new Vue 执行的是 Vue 的构造函数,由于 VueRouter 只是一个插件,不会在 Vue 中的代码里实现添加 $router 的代码,也就是需要我们在 Vue.use(VueRouter) 注册 VueRouter 时,也就是在 install 方法里就将这部分代码写上,然后等待创建 Vue 根实例的时候再执行。

那执行的时机是什么呢?

js 复制代码
// 全局注入的混入,影响注册之后所有创建的 Vue 实例
_Vue.mixin({
     beforeCreate(){ ... }
})

怎么往所有 Vue 实例上添加属性呢?

js 复制代码
// 往 Vue 的原型上添加 $router 属性,则以后创建出来的 Vue 实例都会包含 $router 属性
_Vue.prototype.$router = this.$options.router

这段代码写在 beforeCreate 中,this 的值指向的就是 Vue 实例,那么 this.$options.router 就可以取到传入的 router 选项。

这段代码只需要在创建 Vue 根实例 的时候执行一次,只有这个时候才会传入 router 选项,组件也是 Vue 实例,但是在创建组件的时候不必执行。

js 复制代码
// 创建根实例时,往所有 Vue 实例上添加 $router 属性
_Vue.mixin({
  beforeCreate(){
       // 创建组件的时候不必执行
       if(this.$options.router){
           _Vue.prototype.$router = this.$options.router
       }
   }
})

new Vue ({ router )}创建根实例时会执行混入的 beforeCreate 钩子,这里传入的 router 会挂在 this.$options.router 上(this 此时就是创建出的根实例),将传入的 router 赋值给 _Vue.prototype.$router,就会在以后创建的所有 Vue 实例上添加 $router 属性。且此方法只会在创建根实例时执行一次,因为在创建组件时,不会传入 router 选项。

完整代码

js 复制代码
let _Vue = null
export default class VueRouter {
    static install(Vue){
        // 判断当前插件是否已经被安装
        if(VueRouter.install.installed) return
        VueRouter.install.installed = true
        // 把 Vue 构造函数记录到全局变量中
        _Vue = Vue
        // 创建根实例时,往所有 Vue 实例上添加 $router 属性
        _Vue.mixin({
            beforeCreate(){
                if(this.$options.router){
                    _Vue.prototype.$router = this.$options.router
                }
            }
        })
    }
}    
相关推荐
一拳不是超人3 分钟前
一个没测暗色模式的 Bug,吃掉了我一半 谷歌扩展用户
前端·javascript·程序员
liangshanbo121519 分钟前
React useState 函数式更新面试题整理
前端·react.js·前端框架
涛涛ing24 分钟前
为什么你的页面在 Safari 上总出问题?Interop 2027 正在解决这个 20 年老毛病
前端
不一样的少年_37 分钟前
WebP 压缩到底在干嘛?小白也能看懂的原理拆解
前端·后端·图片资源
问心无愧051338 分钟前
ctf show web 177
前端·笔记
不一样的少年_41 分钟前
PNG/JPG 如何变成 WebP?真相不是改后缀!
前端·后端·图片资源
杉氧1 小时前
RN 性能调优指南:重渲染(Re-renders)控制与长列表(FlatList)优化
android·前端·react native
一_个前端1 小时前
[JS] 一站式搞定 PDF、图片、Dom弹窗、表格的浏览器打印功能
前端
JavaGuide1 小时前
阿里 Qoder 又开源了一个专门给 Claude Code、Codex 做“体检”的项目
前端·后端
不一样的少年_1 小时前
JPEG 压缩到底在干嘛?小白也能看懂的 8 步拆解
前端·后端·图片资源