前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >学习vuex源码

学习vuex源码

作者头像
2014v
发布2019-11-20 11:35:22
4700
发布2019-11-20 11:35:22
举报
文章被收录于专栏:2014前端笔记2014前端笔记

昨天听完同学来我们团队做的分享之后,自己又去看了一遍源码,结合自己之前项目的一些理解,写一篇博客,这里是原文链接.

在看源码前,结合之前的自己的项目实践,有以下几个问题:

  • 1.在mutation以外比如vue组件中修改数据,会报错,是怎么做到的
  • 2.我们在一个组件中拿数据的时候要从mapGetters里面映射过来,为什么要存在这个getter呢?

接下来针对上面的问题,结合源码做一下解答:

我们在一个项目中引入vuex是下面的这样一个注入:

代码语言:javascript
复制
Vue.use(Vuex)
export default new Vuex.Store({
  modules: {
    artical,
    editNews,
    login,
    label,
    user
  }
})

其实从上面的这段代码就不难看出,store应该是一个构造函数,对应着vuex源码中store.js 在store.js中有这样的一段代码,简化如下:

代码语言:javascript
复制
class store {
    constructor(){
        this._committing = false;
    }
      _withCommit (fn) {
        const committing = this._committing
        this._committing = true
        fn()
        this._committing = committing
      }
}

这段代码就很好的解释了第一个问题,当我们通过dispatch一个action之后,数据到达mutation里面,我们会将此时的是否编辑状态更改为true,然而当我们直接在组件中修改的时候,此时的_commiting状态依然为false,所以我们往往是做了一层深拷贝之后,才在组件中对数据进行修改。

接下来是第二个问题,为什么要设置一个getter呢? 在我原先的项目中,我的getters里面基本都是这样的函数

代码语言:javascript
复制
const getters = {
  allTableDatas: state => state.tableData,
  allResult: state => state.result
}

其实就是把state中的状态在原封不动的映射出去,当时我在想为什么需要这层映射,直接把state映射出去不好吗,对于一个module里面,如果state里面数据很多的话,那getters也要写很多,岂不是很烦?

但其实看完源码后发现这层getters是必不可少的,为什么呢?

这首先得追溯到vue是如何实现双向绑定的这个问题上,如果不了解的话,可以去看看我的这一篇博客,vue框架本身在你获取一个数据的时候,比如obj.aa,也就是在这个对象的getter里面,就会把你放进一个通知队列里面,当这个对象被重新setter后,会遍历通知队列告诉你我更新了,你也要更新了,并且如果这个数据有watch的话,同时会执行watch的回调函数。

那一个问题就是vuex中的数据是如何实现双向绑定的呢?是和vue一样的方式吗?vuex的源码非常简洁,里面并没有做和vue同样的事情,其实他正是通过了getter方法,与vue的watch相挂钩,才实现了vuex的双向绑定,来看源码中的如下代码

代码语言:javascript
复制
  watch (getter, cb, options) {
    if (process.env.NODE_ENV !== 'production') {
      assert(typeof getter === 'function', `store.watch only accepts a function.`)
    }
    return this._watcherVM.$watch(() => getter(this.state, this.getters), cb, options)
  }

对于一开始的困惑也就解答完了,那一开始说的新大陆是什么呢?

在项目中,当我们对页面上的数据做一些删除或者更新的操作时,我往往会在更新结束之后,在dispatch一个查询操作,就是这个dispatch其实他是可以接收多个action的,而且向每个action传递的参数也一样(主要是之前也没这么用过,读源码的时候发现还能有这种操作,源码如下:

代码语言:javascript
复制
 . dispatch (_type, _payload) {
    // check object-style dispatch
    const {
      type,
      payload
    } = unifyObjectStyle(_type, _payload)

    const entry = this._actions[type]
    if (!entry) {
      if (process.env.NODE_ENV !== 'production') {
        console.error(`[vuex] unknown action type: ${type}`)
      }
      return
    }
    return entry.length > 1
      ? Promise.all(entry.map(handler => handler(payload)))
      : entry[0](payload)
  }

这篇文章的思路讲的还是比较跳的,没有对源码整体文件目录上做分析就直接讲代码,如果没太看懂的话可以先去看开头的那篇分析,很详细。 最后,欢迎批评指正~

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档