详解如何实现一个简单的 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 相关文章推荐
前端开发过程中浏览器版本的两种判定方法
Oct 30 Javascript
jQuery中使用Ajax获取JSON格式数据示例代码
Nov 26 Javascript
jquery live()重复绑定的解决方法介绍
Jan 03 Javascript
javascript 获取元素样式必杀技
May 04 Javascript
值得分享的Bootstrap Ace模板实现菜单和Tab页效果
Dec 30 Javascript
JavaScript中localStorage对象存储方式实例分析
Jan 12 Javascript
原生js实现可拖拽效果
Feb 28 Javascript
vue mintui-Loadmore结合实现下拉刷新和上拉加载示例
Oct 12 Javascript
JS中Object对象的原型概念基础
Jan 29 Javascript
JsChart组件使用详解
Mar 04 Javascript
Vue动态创建注册component的实例代码
Jun 14 Javascript
比较node.js和Deno
Apr 27 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
实现php加速的eAccelerator dll支持文件打包下载
2007/09/30 PHP
php intval的测试代码发现问题
2008/07/27 PHP
php站内搜索并高亮显示关键字的实现代码
2011/12/29 PHP
php实现比较两个文件夹异同的方法
2015/06/18 PHP
laravel 执行迁移回滚示例
2019/10/23 PHP
javascript 实现父窗口引用弹出窗口的值的脚本
2007/08/07 Javascript
浅谈tudou土豆网首页图片延迟加载的效果
2010/06/23 Javascript
鼠标滑过出现预览的大图提示效果
2014/02/26 Javascript
Jquery设置attr的disabled属性控制某行显示或者隐藏
2014/09/25 Javascript
js仿百度切换皮肤功能(html+css)
2016/07/10 Javascript
JS控制HTML元素的显示和隐藏的两种方法
2016/09/27 Javascript
JS实现拖动滚动条评分的效果代码分享
2016/09/29 Javascript
javascript入门之数组[新手必看]
2016/11/21 Javascript
Bootstrap页面标题Page Header的实现方法
2017/03/22 Javascript
jackson解析json字符串,首字母大写会自动转为小写的方法
2017/12/22 Javascript
Angular开发实践之服务端渲染
2018/03/29 Javascript
微信小程序仿RadioGroup改变样式的处理方案
2018/07/13 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
JS学习笔记之原型链和利用原型实现继承详解
2019/05/29 Javascript
laravel-admin 与 vue 结合使用实例代码详解
2019/06/04 Javascript
Weex开发之地图篇的具体使用
2019/10/16 Javascript
在Vue中使用CSS3实现内容无缝滚动的示例代码
2020/11/27 Vue.js
vue+vant 上传图片需要注意的地方
2021/01/03 Vue.js
[02:28]PWL开团时刻DAY3——Ink Ice与DeMonsTer之间的勾心斗角
2020/11/03 DOTA
Python实现的寻找前5个默尼森数算法示例
2018/03/25 Python
matplotlib.pyplot绘图显示控制方法
2019/01/15 Python
python实现将文件夹内的每张图片批量分割成多张
2019/07/22 Python
matplotlib之pyplot模块之标题(title()和suptitle())
2021/02/22 Python
学院书画协会部门职责
2013/11/28 职场文书
职工运动会感言
2014/02/07 职场文书
2014年幼儿园元旦活动方案
2014/02/13 职场文书
公益广告语集锦
2014/03/13 职场文书
党支部党的群众路线对照检查材料
2014/09/24 职场文书
单身证明格式样本
2015/06/15 职场文书
小学生暑假安全公约
2015/07/14 职场文书
浅谈音视频 pts dts基本概念及理解
2022/08/05 数码科技