详解如何实现一个简单的 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 相关文章推荐
准确获得页面、窗口高度及宽度的JS
Nov 26 Javascript
javascript 客户端验证上传图片的大小(兼容IE和火狐)
Aug 15 Javascript
使用jquery实现select添加实现后台权限添加的效果
May 28 Javascript
一些常用弹出窗口/拖放/异步文件上传等实用代码
Jan 06 Javascript
Javascript实现div层渐隐效果的方法
May 30 Javascript
Angular 理解module和injector,即依赖注入
Sep 07 Javascript
jquery动态添加文本并获取值的方法
Oct 12 Javascript
js仿拉勾网首页穿墙广告效果
Mar 08 Javascript
JavaScript笛卡尔积超简单实现算法示例
Jul 30 Javascript
jquery树形插件zTree高级使用详解
Aug 16 jQuery
bootstrap-closable-tab可实现关闭的tab标签页插件
Aug 09 Javascript
如何构建一个Vue插件并生成npm包
Oct 26 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
PHILIPS AE3805收音机的分析打磨
2021/03/02 无线电
php知道与问问的采集插件代码
2010/10/12 PHP
解密ThinkPHP3.1.2版本之模板继承
2014/06/19 PHP
静态的动态续篇之来点XML
2006/08/15 Javascript
IE6下通过a标签点击切换图片的问题
2010/11/14 Javascript
使用滤镜设置透明导致 IE 6/7/8/9 解析异常的解决方法
2011/04/07 Javascript
jQuery 获取URL的GET参数值的小例子
2013/04/18 Javascript
Javascript页面添加到收藏夹的简单方法
2013/08/07 Javascript
基于jQuery创建鼠标悬停效果的方法
2015/03/07 Javascript
页面内容排序插件jSort使用方法
2015/10/10 Javascript
JavaScritp添加url参数并将参数加入到url中及更改url参数的方法
2015/10/26 Javascript
手机端点击图片放大特效PhotoSwipe.js插件实现
2016/08/24 Javascript
bootstrap栅格系统示例代码分享
2017/05/22 Javascript
Javascript创建类和对象详解
2017/05/31 Javascript
vue组件实现进度条效果
2018/06/06 Javascript
vue中vee validate表单校验的几种基本使用
2018/06/25 Javascript
Javascript中绑定click事件的四种方式介绍
2018/10/26 Javascript
小程序红包雨的实现示例
2019/02/19 Javascript
python 数据清洗之数据合并、转换、过滤、排序
2017/02/12 Python
创建pycharm的自定义python模板方法
2018/05/23 Python
python 批量修改/替换数据的实例
2018/07/25 Python
Python 实例方法、类方法、静态方法的区别与作用
2019/08/14 Python
python多线程并发及测试框架案例
2019/10/15 Python
Python多进程编程常用方法解析
2020/03/26 Python
用纯CSS3实现网页中常见的小箭头
2017/10/16 HTML / CSS
使用html5制作loading图的示例
2014/04/14 HTML / CSS
世界上最大的售后摩托车零配件超市:J&P Cycles
2017/12/08 全球购物
英国床垫和床架购物网站:Bedman
2019/11/04 全球购物
哈萨克斯坦最大的时装、鞋子和配饰在线商店:Lamoda.kz
2019/11/19 全球购物
什么是符号链接,什么是硬链接?符号链接与硬链接的区别是什么?
2014/01/19 面试题
2014年药品销售工作总结
2014/12/16 职场文书
春节慰问简报
2015/07/21 职场文书
考教师资格证不要错过的4个最佳时机
2019/07/17 职场文书
如何使用Python实现一个简易的ORM模型
2021/05/12 Python
详解Flask开发技巧之异常处理
2021/06/15 Python
Java设计模式之享元模式示例详解
2022/03/03 Java/Android