Vuex温故知新

Vuex温故知新

一、Vuex是什么?

Vuex 是专门为vuejs框架设计的 状态管理工具,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

1、Vuex的构成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EMmQP2No-1588057823521)(/Users/liurongjie/dev/workspace/technique-sharing/2020/img/vuex-state.png)]

由上图可以看出主要由以下几个部分组成:

1)state

state是存储的单一状态,是存储的基本部分。

2)Getters

getters 是store的计算属性,对state进行加工运算处理派生出来的数据,与computed类似。

特点:getter返回的数据会根据它的依赖被缓存起来,只有当它的依赖值发生变化时候才会重新计算。

3)Mutations

mutations提交数据变更,调用store.commit()方法提交变更,为同步函数。

4)Actions

actions是一个异步函数,不直接变更数据,而是通过调用store.dispatch()提交mutions函数方式进行数据变更。

5) Module

Module 是store分割的模块,每个模块都有自己的state、getters、mutations、actions。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
6) 辅助函数

Vuex提供了mapState、MapGetters、MapActions等辅助函数给开发在vm中处理store

demo:

mapState

# 引入
import {mapState}  from 'Vuex'

# 使用
computed: mapState({
  // 箭头函数
  count: state => state.count,
  // 这里为了能够使用this获取局部变量localCount,必须使用常规函数
  countPlusLocalState (state) {
    return state.count + this.localCount
  }
})

2、Vuex的使用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gYJAMjDT-1588057823524)(/Users/liurongjie/dev/workspace/technique-sharing/2020/img/vuex-2.png)]

import Vuex from 'vuex';
Vue.use(Vuex); // 1. vue的插件机制,安装vuex
let store = new Vuex.Store({ // 2.实例化store,调用install方法
    state,
    getters,
    modules,
    mutations,
    actions,
    plugins
});
new Vue({ // 3.注入store, 挂载vue实例
    store,
    render: h=>h(app)
}).$mount('#app');

二、Vuex的设计思想

Vuex将数据存储到全局的store,再将store挂载到每个vue实例组件中,利用Vue.js的细粒度数据相应机制来进行高效的状态更新。

三、Vuex原理解析

1、vuex的store是如何挂载注入到组件中的呢?

1)、在vue项目中先安装vuex,核心代码如下:

import Vuex from 'vuex';
Vue.use(vuex);// vue的插件机制

2)、利用vue的插件机制,使用Vue.use(Vuex)时,会调用Vuex的isntall方法,装载Vuex install方法如下:

export function install (_Vue) {
  if (Vue && _Vue === Vue) {
    if (process.env.NODE_ENV !== 'production') {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

3)、applyMixin方法使用Vue 混入机制,vue的生命周期 beforeCreate的钩子函数前混入vuexinit方法,核心代码如下:

Vue.mixin({ beforeCreate: vuexInit });

function vuexInit () {
    const options = this.$options
    // store injection
    if (options.store) {
      this.$store = typeof options.store === 'function'
        ? options.store()
        : options.store
    } else if (options.parent && options.parent.$store) {
      this.$store = options.parent.$store
    }
}

分析源码,我们知道了vuex是利用vue的mixin混入机制,在beforeCreate钩子前混入vuexInit方法,vuexInit方法实现了store注入vue组件实例,并注册了vuex store的引用属性$store。store注入过程如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TmyzJHx1-1588057823526)(/Users/liurongjie/dev/workspace/technique-sharing/2020/img/vuex-install.png)]

2、vuex的state和getters是如何映射到各个组件实例中响应式更新状态?

store实现的源码在src/store.js

1)、在源码中找到resetStoreVM核心方法

function resetStoreVM (store, state, hot) {
  const oldVm = store._vm

  // 设置 getters 属性
  store.getters = {}
  const wrappedGetters = store._wrappedGetters
  const computed = {}
  // 遍历 wrappedGetters 属性
  forEachValue(wrappedGetters, (fn, key) => {
    // 给 computed 对象添加属性
    computed[key] = partial(fn, store)
    // 重写 get 方法
    // store.getters.xx 其实是访问了store._vm[xx],其中添加 computed 属性
    Object.defineProperty(store.getters, key, {
      get: () => store._vm[key],
      enumerable: true // for local getters
    })
  })

  const silent = Vue.config.silent
  Vue.config.silent = true
  // 创建Vue实例来保存state,同时让state变成响应式
  // store._vm._data.$$state = store.state
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  })
  Vue.config.silent = silent

  // 只能通过commit方式更改状态
  if (store.strict) {
    enableStrictMode(store)
  }
}

分析源码我们可以看出Vuex的state状态是响应式,是借助vue的data是响应式,将state存入vue实例组件的data中;Vuex的getters则是借助vue的计算属性computed实现数据实时监听。

computed计算属性监听data数据变更主要经历以下几个过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zgzYthag-1588057823527)(/Users/liurongjie/dev/workspace/technique-sharing/2020/img/v2-2730644102b66eef140110b814a90496_720w.png)]

总结:

Vuex是通过全局注入store对象,来实现组件间的状态共享。

by 刘荣杰

2020.04.16

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值