经过上一篇的介绍,了解到了 Vuex 的实现本质就是一个插件,所以要做的事情就是实现这个插件的代码编写即可。
本篇文章主要是实现一个全局的 $store
,这个 $store
是挂载在 Vue 的原型上的,所以在任何一个组件当中都可以通过 this.$store
访问到。
我们先来看看 Vue 官方的,我们分别在 App.vue, HelloWorld.vue 中打印 this.$store
,看看能不能访问到。
mounted() {
console.log(this.$store);
}
可以看到都访问到了,那么我们就可以开始实现了。
官方开发插件文档:https://cn.vuejs.org/guide/reusability/plugins.html
我这里直接上代码,创建一个 Nuex.js 文件,在文件中先简单的暴露一个 install 方法。
这个 install 方法是 Vue.use() 调用的,所以在这个方法中可以接收到 Vue 的实例,然后在这个方法中实现我们的逻辑。
在使用 Vuex 的时候需要传递一个 store 对象,这个 store 对象就是我们的仓库,所以我们还需要在 Nuex.js 文件中暴露一个 Store 属性,这个属性的取值是一个类。
最终的代码如下:
/**
* install方法会在外界调用Vue.use的时候执行
* 并且在执行的时候会把Vue实例和一些额外的参数传递给我们
* @param Vue Vue实例
* @param options 额外的参数
*/
const install = (Vue, options) => {
}
export default {
install
}
这样我们的插件就创建完毕了,接下来就是在 install 方法中实现我们的逻辑。给每一个Vue实例都添加一个 $store
属性。
在Vue中有一个名称叫做mixin方法,这个方法会在创建每一个Vue实例的时候执行,所以我们可以通过mixin方法给每一个Vue实例添加 $store
属性。
紧接着继续改写我们的代码,调用 Vue.mixin 方法重写 beforeCreate 方法,这个方法会在每一个组件创建的时候执行。
具体的核心逻辑我这里先不写,我先在 beforeCreate 方法中打印一下组件的一些参数信息。
打开浏览器控制台,运行结果如下:
可以看到在 beforeCreate 方法中打印了三次,Vue 实例化的时候会先实例化根组件,然后在实例化根组件的时候会先实例化子组件,所以会打印三次。(Vue,App, HelloWorld)
如何验证这个结论呢那么就是分别打印一下实例化组件的名称,根组件还没有添加 name 属性,先给我们的根组件也取一个名字,叫做 root:
在更改下 beforeCreate 方法打印的属性值为 $options.name
即可:
返回浏览器控制台观察输出结果:
输出的内容和我们的结论是一致的,知道了实例化的过程之后,接下来就是完善核心逻辑即可,我们知道在实例化过程中,首先实例化的是根组件,然后在实例化根组件的时候会先实例化子组件,所以我们可以在实例化根组件的时候给根组件添加一个 $store
属性,然后在实例化子组件的时候直接从父组件中取出 $store
属性赋值给子组件即可。
在根组件中有一个 store,只要将这个 store 赋值给 $store
即可,那么在子组件中就可以通过 this.$store
访问到了。
有了思路之后,我们就可以开始编写代码了,最终实现的代码如下:
beforeCreate() {
/*
如果是根组件, 那么默认就有store
我们只需要将store变成$store即可
*/
if (this.$options && this.$options.store) {
this.$store = this.$options.store;
} else {
/*
如果不是根组件, 那么默认没有store
我们只需要将它父组件的$store赋值给它即可
*/
this.$store = this.$parent.$store;
}
}
然后在将之前组件中访问 this.$store
的代码放开(取消注释):
然后重新运行项目,可以看到可以访问到 this.$store
:
到这里添加全局 $store
的代码就完成了(还没有实现数据共享,所以在各个组件当中访问共享数据的代码我都是注释掉了)。