详解如何实现一个简单的 vuex


Posted in Javascript onFebruary 10, 2018

首先我们需要知道为何要使用 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
})

// 使用 bus
app.$options.bus

// or
this.$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 代码的实现如下:

<div id="app">
 <child-a></child-a>
 <child-b></child-b>
</div>

非父子组件的实现

然后是两个非父子组件和 app 的实现,子组件都使用到了 bus 的 count,这里用 store.state 表示,跟 vuex 一致:

// 待实现
const store = new Store(Vue, {
 state: {
  count: 0
 }
})

// 子组件 a
const childA = {
 template: '<button @click="handleClick">click me</button>',
 methods: {
  handleClick () {
   this.$store.state.count += 1
  }
 }
}

// 子组件 b
const childB = {
 template: '<div>count: {{ count }}</div>',
 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 的实现,两步实现:

  1. 创建一个 bus 实例;
  2. 让子组件都能访问到 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,从而实现了非父子组件之间的响应同步。全部源码参考这里 。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript 基础篇1 什么是js 建立第一个js程序
Mar 14 Javascript
jquery异步跨域访问代码
Jun 28 Javascript
Javascript中拼接大量字符串的方法
Feb 05 Javascript
js随机生成网页背景颜色的方法
Feb 26 Javascript
JS中使用apply方法通过不同数量的参数调用函数的方法
May 31 Javascript
JavaScript的this关键字的理解
Jun 18 Javascript
深入学习 JavaScript中的函数调用
Mar 23 Javascript
JavaScript实现三级联动菜单效果
Aug 16 Javascript
微信小程序实现的点击按钮 弹出底部上拉菜单功能示例
Dec 20 Javascript
页面内锚点定位及跳转方法总结(推荐)
Apr 24 Javascript
解决在layer.open中使用时间控件laydate失败的问题
Sep 11 Javascript
浅谈vue中$bus的使用和涉及到的问题
Jul 28 Javascript
vue实现微信分享朋友圈,发送朋友的示例讲解
Feb 10 #Javascript
使用 vue.js 构建大型单页应用
Feb 10 #Javascript
javascript中的隐式调用
Feb 10 #Javascript
VUEJS 2.0 子组件访问/调用父组件的实例
Feb 10 #Javascript
webpack之devtool详解
Feb 10 #Javascript
React组件refs的使用详解
Feb 09 #Javascript
详解vue-cli项目中的proxyTable跨域问题小结
Feb 09 #Javascript
You might like
第二节--PHP5 的对象模型
2006/11/16 PHP
php与mysql建立连接并执行SQL语句的代码
2011/07/04 PHP
php防止表单重复提交实例讲解
2019/02/11 PHP
PHP+Oracle本地开发环境搭建方法详解
2019/04/01 PHP
用javascript实现给图片加链接
2007/08/15 Javascript
基于jQuery的可以控制左右滚动及自动滚动效果的代码
2010/07/25 Javascript
jQuery获取css z-index在各种浏览器中的返回值
2010/09/15 Javascript
javascript Array.prototype.slice的使用示例
2013/11/14 Javascript
jquery+css实现动感的图片切换效果
2015/11/25 Javascript
jQuery制作网页版选项卡
2016/07/28 Javascript
深入理解requestAnimationFrame的动画循环
2016/09/20 Javascript
Bootstrap基本模板的使用和理解1
2016/12/14 Javascript
微信小程序 本地数据读取实例
2017/04/27 Javascript
详解vue数据渲染出现闪烁问题
2017/06/29 Javascript
vue 路由子组件created和mounted不起作用的解决方法
2019/11/05 Javascript
js实现简单选项卡制作
2020/08/05 Javascript
[59:30]VG vs LGD 2019国际邀请赛淘汰赛 胜者组 BO3 第二场 8.22
2019/09/05 DOTA
简述Python中的面向对象编程的概念
2015/04/27 Python
Python从MP3文件获取id3的方法
2015/06/15 Python
深入解析Python中的__builtins__内建对象
2016/06/21 Python
面向对象学习之pygame坦克大战
2019/09/11 Python
Pandas对DataFrame单列/多列进行运算(map, apply, transform, agg)
2020/06/14 Python
python线程池 ThreadPoolExecutor 的用法示例
2020/10/10 Python
Django url 路由匹配过程详解
2021/01/22 Python
HTML5中input[type='date']自定义样式与日历校验功能的实现代码
2017/07/11 HTML / CSS
Python如何实现单例模式
2016/06/03 面试题
师范大学音乐表演专业求职信
2013/10/23 职场文书
留学推荐信中文范文三篇
2014/01/25 职场文书
2014自荐信的写作技巧
2014/01/28 职场文书
黄河象教学反思
2014/02/10 职场文书
男女朋友协议书
2014/04/23 职场文书
慰问敬老院活动总结
2014/04/26 职场文书
读书伴我成长演讲稿
2014/05/07 职场文书
学习雷锋主题班会
2015/08/14 职场文书
教师节作文之小学四年级
2019/09/03 职场文书
python实现ROA算子边缘检测算法
2021/04/05 Python