首先我们需要知道为何要使用 vuex。父子组件通信用 prop 和自定义事件可以搞定,简单的非父子组件通信用 bus(一个空的 vue 实例)。那么使用 vuex 就是为了解决复杂的非父子组件通信。
仅仅会使用 vuex 没什么,看过文档敲敲代码大家都会。难道你就不想知道 vuex 是如何实现的?!
抛开 vuex 的源码,我们先来想想如何实现一个简单的 vuex。有多简单呢,我不要 getter、mutation、action 等,我只要 state 就行了。
非父子组件通信
在实现之前,我们得来温故一下 bus 的实现,借用官网的例子:
var bus = new vue()// 触发组件 a 中的事件bus.$emit('id-selected', 1)// 在组件 b 创建的钩子中监听事件bus.$on('id-selected', function (id) { // ...})
遥想当年,实例化后的 bus 不知放哪好,最后无奈将其放到了 window 下,一直 window.bus 的使用。虽然这样也没问题,但还是影响到了全局作用域。
突然的某一天,我发现可以挂载在 vue 的根实例下(从此告别 window.bus),于是便有了:
var app = new vue({ el: '#app', bus: bus})// 使用 busapp.$options.bus// orthis.$root.$options.bus
然后又发现了,bus 其实不只是 on 事件才可以通信。其实 bus 是一个 vue 实例,其中 data 是响应的。比如在 app 这个根实例下有两个非父子组件,都使用到了 bus 的 data,那么它们是响应同步的。
var bus = new vue({ data: { count: 0 }})
以上,子组件 a 修改了 count,如果子组件 b 有用到 count,那么它就能响应到最新 count 的值。
说了这么多,你还没发现吗?这个不就是实现了非组件之间通信,vuex 的 state 吗?!
封装 bus
是的,把刚刚的 bus 封装一下,这个就是一个最简单的 "vuex" (仅仅只有 state 的功能)。首先,我们将有一个根实例 app ,实例下有两个非父子组件 childa 和 childb 。
html 代码的实现如下:
<p id="app"> <child-a></child-a> <child-b></child-b></p>
非父子组件的实现
然后是两个非父子组件和 app 的实现,子组件都使用到了 bus 的 count,这里用 store.state 表示,跟 vuex 一致:
// 待实现const store = new store(vue, { state: { count: 0 }})// 子组件 aconst childa = { template: '<button @click="handleclick">click me</button>', methods: { handleclick () { this.$store.state.count += 1 } }}// 子组件 bconst childb = { template: '<p>count: {{ count }}</p>', computed: { count () { return this.$store.state.count } }}new vue({ el: '#app', components: { 'child-a': childa, 'child-b': childb }, store: store})
看到代码里还有一个 store 待实现。所需要的参数,因为这里懒得用 vue.use() ,所以直接将 vue 作为参数传入以供使用,然后第二个参数跟我们使用 vuex 传入的参数一致。
store 的实现
接下来就是 store 的实现,两步实现:
创建一个 bus 实例;
让子组件都能访问到 this.$store。
第 1 步骤上面已经有了,第 2 步骤主要用到了 vue.mixin 来全局混入,但仅仅只是找到有 store 的根实例并赋值 vue 原型上的 store,也能够让根实例 app 不用专门写 mixins 混入。
class store { constructor (vue, options) { var bus = new vue({ data: { state: options.state } }) this.install(vue, bus) } install (vue, bus) { vue.mixin({ beforecreate () { if (this.$options.store) { vue.prototype.$store = bus } } }) }}
实现的 store 就是一个简单的 vuex,它拥有了 vuex 的 state,足够让非父子组件之间进行简单通信。
在 store 的构造函数里创建一个 bus 实例,并将其注入 vue 的原型,实现了组件都能访问到 this.$store 即 bus 实例。 this.$store 就是一个 vue 实例,所以访问了 this.$store.state.count 实际上就是访问到了 data,从而实现了非父子组件之间的响应同步。全部源码参考这里 。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
使用node应用中timing-attack存在哪些安全漏洞
在vue组件传递对象中实现单向绑定,该怎么做?
在vue组件中如何使用 typescript的方法(详细教程)
以上就是详解如何实现vuex(详细教程)的详细内容。
