Bootstrap

【Vuex 源码学习】第二篇 - vuex 插件安装 install 逻辑

一,前言

上一篇,介绍了 vuex 的基本用法,主要包含以下几个点:

  • vuex 项目创建;

  • vuex 工作流程介绍;

  • vuex 的基本使用介绍;

本篇,继续介绍 vuex 的 install 插件安装逻辑;

二,vuex 插件安装逻辑的实现

1,前文回顾

上一篇,在介绍 vuex 的基本用法前,先安装了 vuex 插件,并进行了相关的配置:

// src/store/index.js

import Vue from 'vue';
import Vuex from 'vuex';

// 注册 vuex 插件:内部会调用 Vuex 中的 install 方法
Vue.use(Vuex);

// 实例化容器容器:Vuex.Store
const store = new Vuex.Store({
  ...
});

// 导出 store 实例,传入根组件
export default store; 

将 store 实例注入到 vue 中:

// src/main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store/index' // 引入 store 实例

Vue.config.productionTip = false

new Vue({
  store,// 将 store 实例注入到 vue 中
  render: h => h(App),
}).$mount('#app');

使用 vuex:

从 Vuex 的使用方式可以看出:

  • Vuex 是一个对象,内部存在一个 install 方法,当 Vue.use 时执行插件安装逻辑;

  • vuex 中包含了一个 Store 类;

  • 与 vue-router 相似,插件安装时,向所有组件混入了 store 属性;

2,创建 vuex 插件

vuex 的以上特点,创建 vuex 目录及入口文件 src/vuex/index.js,其中包含 Store 类和 install 方法并导出:

// 容器的初始化
class Store {

}

// 插件安装逻辑:当Vue.use(Vuex)时执行
const install =()=>{

}

export default {
    Store,
    install
}

3,模块化设计

  • Store 类作用:容器的初始化

  • install 方法作用:插件安装逻辑

  • src/vuex/index.js 文件作用:作为 vuex 插件入口,导出方法供外部调用;

所以,这里进行模块化设计,将 Store 类和 install 方法抽离,使 index.js 仅用于方法聚合并导出;

创建 src/vuex/store.js 文件,将 Store 类和 install 方法单独在外部实现并向外导出:

// src/vuex/store.js

// 容器的初始化
export class Store {

}

// 插件安装逻辑:当Vue.use(Vuex)时执行
export const install =()=>{

}

src/vuex/index.js 中,聚合导出的两个方法并导出:

// src/vuex/index.js

import { Store, install } from './store';

export default {
    Store,
    install
}

这样,后续 vuex 插件相关方法可以通过此方式对外导出,如:mapState 等方法;

4,install 插件安装逻辑

vuex 与 vue-router 的插件安装逻辑相似;

当执行时,install 方法会传入 vue 的构造函数,实现 vuex 插件与项目使用的 Vue 版本一致:

// src/vuex/store.js

// 导出传入的 Vue 的构造函数,供插件内部的其他文件使用
export let Vue;

/**
 * 插件安装逻辑:当Vue.use(Vuex)时执行
 * @param {*} _Vue Vue 的构造函数
 */
export const install = (_Vue) => {
  Vue = _Vue;
}

同时,会将 new Vue 时(根组件)注入的 store 容器实例,混入到所有组件中,为所有组件添加 store 属性:

创建 src/vuex/mixin.js,使用 Vue.mixin 实现全局混入:

// src/vuex/mixin.js

/**
 * 将根组件中注入store实例,混入到所有子组件上
 * @param {*} Vue 
 */
export default function applyMixin(Vue) {
  // 通过 beforeCreate 生命周期,在组件创建前,实现全局混入
  Vue.mixin({
    beforeCreate: vuexInit,// vuexInit为初始化混入逻辑
  });
}

在 store.js 中引入,并在 install 时调用:

// src/vuex/store.js

import applyMixin from "./mixin";

export const install = (_Vue) => {
  Vue = _Vue;
  applyMixin(Vue);
}

混入逻辑:

由于组件渲染是先渲染父组件再渲染子组件,这样根组件中注入的 store 实例,就可以被混入到 App.vue 组件上。依次类推,由父组件向子组件传递 store 实例,实现全局共享;

function vuexInit() {
  const options = this.$options;
  // 如果选项中拥有store属性,说明是根实例;其他情况都是子实例
  if (options.store) {// 根实例
    // 为根实例添加 $store 属性,指向 store 实例
    this.$store = options.store;
  } else if (options.parent && options.parent.$store) { // 子实例
    // 儿子可以通过父亲拿到 $store 属性,放到自己身上继续给儿子
    this.$store = options.parent.$store;
  }
}

5,测试混入效果

引入新创建的 vuex 作为插件:

// src/store/index.js

import Vue from 'vue';
// import Vuex from 'vuex';
import Vuex from '@/vuex';

在 App.vue 中,打印组件上的 $store 属性,是否混入了来自根组件的 store 实例:

// src/App.vue

执行 npm run serve 启动服务:

输出结果:Store {}

混入成功!

三,结尾

本篇,介绍了 vuex 的 install 插件安装逻辑,包含以下几个点:

  • 创建 vuex 插件目录;

  • 模块化设计;

  • 实现插件安装install时store实例混入逻辑;

  • 混入效果测试;

下一篇,介绍 Vuex 中 State 状态的实现;