写点什么

【Vuex 源码学习】第三篇 - Vuex 中 State 状态的实现

用户头像
Brave
关注
发布于: 刚刚
【Vuex 源码学习】第三篇 - Vuex 中 State 状态的实现

一,前言


上篇,介绍了 vuex 的 install 插件安装逻辑,包含以下几个点:


  • 创建 vuex 插件目录;

  • 模块化设计;

  • 实现插件安装 install 时 store 实例混入逻辑;

  • 混入效果测试;


本篇,继续介绍 Vuex 中 State 状态的实现;


二,前文回顾


上一篇提到,当外部执行`Vue.use(Vuex)`时,会调用 Vuex 对象上的 install 方法进行插件安装,通过 `Vue.mixin` 全局混入的方式,将`new Vue`(根组件)时注入的 store 容器实例,在 beforeCreate 生命周期,即组件创建前,混入到所有组件中,为所有组件添加 store 属性;
这样就实现了 store 容器实例的全局混入;
复制代码


在页面中使用 Vuex 时:

// src/App.vue
<template> <div id="app"> 商品数量: {{this.$store.state.num}} 个<br> 商品单价: 10 元<br> 订单金额: {{this.$store.getters.getPrice}} 元<br> <button @click="$store.commit('changeNum',5)">同步更新:数量+5</button> <button @click="$store.dispatch('changeNum',-5)">异步更新:数量-5</button> </div></template>
复制代码


state、getters、commit、dispatch 这些方法均来自 store 实例


三,创建 Store 类中的 State 状态


new Vuex.Store 时,传入了一个配置对象:

// 实例化容器容器:Vuex.Storeconst store = new Vuex.Store({state,mutation,actions});
复制代码


所以,在 Store 类的构造方法中,需要有一个配置对象 options 作为入参:

// src/vuex/store.js
// Vuex 的容器export class Store { constructor(options) { // options:{state, mutation, actions} const state = options.state; // 获取 options 选项中的 state 对象 }}
复制代码


在 Vuex 中,state 中的状态要求是响应式的,即数据变化可以触发更新的视图;

而当前 Store 类中的 state 是死值,并不具备响应式;

<template>  <div id="app">    商品数量: {{this.$store.state.num}} 个<br>    商品单价: 10 元<br>    订单金额: {{this.$store.getters.getPrice}} 元<br>    <button @click="$store.commit('changeNum',5)">同步更新:数量+5</button>    <button @click="$store.dispatch('changeNum',-5)">异步更新:数量-5</button>    <!-- 测试 State 数据响应式 -->    <button @click="$store.state.num = 100">测试 State 数据响应式</button>  </div></template>
复制代码


通过点击页面中的按钮,直接修改 $store 中的 State 值,页面是不会更新的;

视图没有跟进的原因:因为 num 并不是响应式数据,不会进行依赖收集,数据变化后不会更新;


四,实现 State 状态的响应式


实现 State 数据的响应式,可以将 State 数据放到 vue 的 data 中,借助 Vue 的响应式实现:

// src/vuex/store.js
export class Store { constructor(options) { // options:{state, mutation, actions} const state = options.state; // 获取 options 选项中的 state 对象
// 响应式数据:new Vue({data}) this._vm = new Vue({ data: { // 在 data 中,默认不会将以$开头的属性挂载到 vm 上 $$state: state // $$state 对象将通过 defineProperty 进行属性劫持 } }) } get state() { // 对外提供属性访问器:当访问state时,实际是访问 _vm._data.$$state return this._vm._data.$$state }}
复制代码


这里有一个技巧:在 Vue 中,以$开头的属性是内部的,默认不会被挂载到 vm 上的;即不能通过 vm.$$state 获取,只能通过 _vm._data.$$state 访问,而 _data 是素有属性;
复制代码


当外部通过 store.state 获取状态对象时,相当于拿到了 this._vm._data.$$state,get state()是 ES6 语法属性访问器,相当于 Object.defineProperty({}) 中的 getter ;


// todo _data 相关知识可联动 Vue2.x 源码的《数据代理实现》


总结:vuex 中 state 状态的响应式是借助了 Vue 来实现的;
响应式数据在页面渲染时会进行依赖收集,当 store 中的 state 状态改变时,就会触发视图的更新操作;
复制代码



五,结尾


本篇,介绍了 Vuex 中 State 状态的实现,主要涉及以下几个点:


  • 创建 Store 类中的 State 状态;

  • 借助 Vue 实现 State 状态的响应式;


下一篇, Vuex 中 getter 的实现;

用户头像

Brave

关注

还未添加个人签名 2018.12.13 加入

还未添加个人简介

评论

发布
暂无评论
【Vuex 源码学习】第三篇 - Vuex 中 State 状态的实现