vue vue-router vuex 是怎么实现的

206 阅读1分钟

vue-router的实现

是个 function 或 Object,其内必须有一个 install,将来会被vue.use(vue3 里 app.use)调用

let Vue // 保存Vue构造函数,插件中使用,并保持独立
class VueRouter {
    constructor (options) {
        this.$options = options
        // 把current作为响应式数据
        // 将来发生变化,router-view的render函数能再次执行
        this.current = '/'
        const initial = window.location.hash.slice(1) || '/'
        Vue.util.defineReactive(this, 'current', initial)
    }
    window.addEventListener('hashchange', () => {
        this.current = window.location.hash.slice(1)
    })
}
VueRouter.install = function (_Vue) { // 参数作为构造函数,要保证这个参数跟这个插件保持独立
 Vue = _vue
 // 1. 挂载$rouer属性,犹豫此插件 调用install的时机比创建时机早,所以为了可以实现this.$rouer.push()我们可以使用混入的方式实现
 // this.$rouer.push()
 // 全局混入
 Vue.mixin({
     beforeCreate () {
         // 此钩子在每个组件实例时都会被调用
         // 根实例才有该选项
         if (this.$options.router) {
             Vue.prototype.$router = this.$options.router
         }
     }
 })
 
 // 2. 注册实现两个组件 router-view,router-link
 Vue.component('router-link', {
     props: {
         to: {
             type: String,
             required: true
         }
     },
     render (h) {
         return h('a', {
             attrs: {
                 href: "#" + this.to
             }
         }, this.$slots.default)
     }
 })
 Vue.component('router-view', {
      props: {
          to: {
              type: String,
              required: true
          }
      },
      render (h) {
          // 获取当前路由对应的组件
          let component = null
          const route = this.$router.$options.routers.find(router => route.path === this.$router.current)
          if (route) {
              compenent = route.component
          }
          return h(component)
      }
 })
}

export default VueRouter

vuex

// 1.挂载$store
// 2.实现Store
let Vue
class Store {
    constructor (options) {
        // data响应式处理
        this._vm = new Vue({
            data: {
                $$state: options.state // 双$会被隐藏不想让你看
            }
        })
        this._mutations = options.mutaions
        this._actions = options.actions
        this.commit = this.commit.bind(this)
        this.dispatch = this.dispatch.bind(this)
    }
    
    get state () {
        return this._vm._data.$$state
    }
    
    commit (type, payload) {
        const entry = this._mutations[type]
        if (!entry) {
            console.error('不能获取到相应的mutations')
        }
        entry(this.state, payload)
    }
    
    dispatch (type, payload) {
        const entry = this._actions[type]
        if (!entry) {
            console.error('不能获取到相应的actions')
        }
        entry(this, payload)
    }
}

function install (_Vue) {
    Vue = _vue
    Vue.mixin({
        beforeCreate () {
            if (this.$options.store) {
                Vue.prototype.$store = this.$options.store
            }
        }
    })
}

export default { Store, install }