详解如何实现一个简单的 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 相关文章推荐
用roll.js实现的图片自动滚动+鼠标触动的特效
Mar 18 Javascript
取键盘键位ASCII码的网页
Jul 30 Javascript
jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、Chrome、Opera
Aug 28 Javascript
浅谈Javascript数组索引
Jul 29 Javascript
微信小程序开发之Tabbar实例详解
Jan 09 Javascript
Javascript同时声明一连串(多个)变量的方法
Jan 23 Javascript
angularJs的ng-class切换class
Jun 23 Javascript
基于Vue过渡状态实例讲解
Sep 14 Javascript
详解Vue2 SSR 缓存 Api 数据
Nov 20 Javascript
jq.ajax+php+mysql实现关键字模糊查询(示例讲解)
Jan 02 Javascript
JS实现调用本地摄像头功能示例
May 18 Javascript
layui表格 返回的数据状态异常的解决方法
Sep 10 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
解决Laravel 不能创建 migration 的问题
2019/10/09 PHP
laravel框架中视图的基本使用方法分析
2019/11/23 PHP
PHP 实现缩略图
2021/03/09 PHP
div移动 输入框不能输入的问题
2009/11/19 Javascript
javascript算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2012/07/21 Javascript
javascript面向对象包装类Class封装类库剖析
2013/01/24 Javascript
jQuery方法简洁实现隔行换色及toggleClass的使用
2013/03/15 Javascript
jquery实现炫酷的叠加层自动切换特效
2015/02/01 Javascript
javascript组合使用构造函数模式和原型模式实例
2015/06/04 Javascript
JavaScript数组对象赋值用法实例
2015/08/04 Javascript
每天一篇javascript学习小结(属性定义方法)
2015/11/19 Javascript
AngularJS使用ngMessages进行表单验证
2015/12/27 Javascript
简单实现js选项卡切换效果
2016/02/03 Javascript
JS实现在文本指定位置插入内容的简单示例
2017/12/22 Javascript
vue移动端UI框架实现QQ侧边菜单组件
2018/03/09 Javascript
vue--点击当前增加class,其他删除class的方法
2018/09/15 Javascript
JS实现盒子跟着鼠标移动及键盘方向键控制盒子移动效果示例
2019/01/29 Javascript
python批量修改文件编码格式的方法
2018/05/31 Python
Python代理IP爬虫的新手使用教程
2019/09/05 Python
Python tkinter和exe打包的方法
2020/02/05 Python
windows下python安装pip方法详解
2020/02/10 Python
Python通过zookeeper实现分布式服务代码解析
2020/07/22 Python
Pycharm创建python文件自动添加日期作者等信息(步骤详解)
2021/02/03 Python
英国鞋类及配饰零售商:Kurt Geiger
2017/02/04 全球购物
澳大利亚在线生活方式商店:Mytopia
2018/07/08 全球购物
群众路线剖析材料
2014/02/02 职场文书
预备党员政审材料
2014/02/04 职场文书
先进集体事迹材料
2014/02/17 职场文书
城市规划应届毕业生自荐信
2014/07/04 职场文书
护士个人总结范文
2015/02/13 职场文书
计算机专业自荐信范文
2015/03/26 职场文书
2019年第四季度财务部门工作计划
2019/11/02 职场文书
阿里云Nginx配置https实现域名访问项目(图文教程)
2021/03/31 Servers
【海涛教你打dota】体验一超神发条:咱是抢盾专业户
2022/04/01 DOTA
vue使用watch监听属性变化
2022/04/30 Vue.js
Centos7 Shell编程之正则表达式、文本处理工具详解
2022/08/05 Servers