一,前言
本篇开始,进入 vuex 源码学习,本篇主要介绍一下内容:
- 创建 vuex 源码项目;
- 介绍 vuex 的基本使用;
二,创建 vuex 源码项目
1,使用 vue-cli 创建 vue2.x 脚手架
vue create source-learning-vuex
脚手架配置项:
Vue CLI v4.5.13
? Please pick a preset: Manually select features
? Check the features needed for your project:
❯◯ Choose Vue version
◉ Babel
◯ TypeScript
◯ Progressive Web App (PWA) Support
◯ Router
◯ Vuex
◯ CSS Pre-processors
◯ Linter / Formatter
◯ Unit Testing
◯ E2E Testing
2,安装 vuex 依赖
npm install vuex
3,创建 .gitignore 文件
创建 .gitignore 文件,忽略掉不需要版本控制的文件:
// .gitignore
.DS_Store
node_modules
/dist
准备工作完成;
二,vuex 的工作流程
vuex 为项目开发提供了状态管理及数据共享能力;
在项目开发中,使用 vuex 能够将所有的数据统一存储到一个 store 容器中进行管理;
如下图所示,绿色虚线框即为 vuex 的管理范围,表示一个容器:
- 在 vuex 中,进行统一的项目状态管理,可以通过 vuex 将状态映射到项目任何组件;
- 在 vuex 中,通过 mutation 是更新状态的唯一方式;
- 状态同步更新:通过直接将结果提交到 mutation,实现状态的同步更新;
- 状态异步更新:通过调用 dispatch 方法,触发对应 action 执行异步操作,并将异步操作的结果提交至 mutation 实现状态的同步更新;
- 日常项目开发中,也可以借助 vuex 的状态管理特性,实现前端的数据缓存功能;
三,vuex 的基本使用介绍
1,vuex 的核心概念
在 vuex 官方文档中,核心概念共有以下五个:
- State:状态,可以理解为 vue 组件中的 data 数据;
- Getter:可以理解为 vue 中的 computed 计算属性;
- Mutation:同步函数,可以同步更改状态;
- Action:异步函数,可以执行异步操作,配合 Mutation 实现状态的异步更新;
- Module: vuex 的模块化,能够将臃肿复杂的 store 容器进行模块化分割,每个模块拥有独立的 state、mutation、action、getter;
2,vuex 插件配置
引入并通过Vue.use(Vuex)
安装 vuex 插件,配置并导出 store 实例:
// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
// 注册 vuex 插件:内部会调用 Vuex 的 install 方法
Vue.use(Vuex);
// 实例化容器:Vuex.Store
const store = new Vuex.Store({
// state 状态:相当于组件中的 data 数据
state: {
num: 10
},
// getters 相当于计算属性(内部实现利用了计算属性)
getters: {
},
// 相当于 method,能够同步的更改 state
mutations: {
},
// action作用:执行异步操作,并将结果提交给 mutations
actions: {
}
});
export default store;// 导出 store 实例,传入根组件
备注:此处为简单配置,尚未引入 Vuex 模块化及命名空间概念;
在 main.js 中导入配置完成的 store 实例;
在new Vue
初始化时,将 store 实例注入根组件:
// main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store/index' // 引入 store 实例
new Vue({
store,// 将 store 实例注入到 vue 中
render: h => h(App),
}).$mount('#app');
此时,vuex 插件配置完成,可直接在页面中测试使用;
3,state 的使用
在 App.vue 中, template
中直接输出 store 容器中的状态 num:
// src/App.vue
<template>
<div id="app">
商品数量: {{this.$store.state.num}} 个<br>
</div>
</template>
执行 npm run serve
启动服务:
问题:this.$store.state.num
是如何获取到状态的?
这里涉及 Vuex 插件初始化,与 vue-router 安装流程相似;
当执行`Vue.use(Vuex)`时,会调用 install 方法,为每个子组件都混入了当前的 store 容器实例;
new Vue 是根实例;App.vue 是根实例的子组件;
所以,new Vue 中传入的 store 实例,install 时会被混入到 App.vue 组件上;
同理,最终所有组件都将混入来自父组件的 store 实例,从而实现 store 容器实例的共享;
4,getters 的使用
getters 的内部实现依赖了 computed;
所以,可以理解为 Vue 的 computed 计算属性;
// main.js
import Vue from 'vue';
import Vuex from 'vuex';
// 注册 vuex 插件:内部会调用 Vuex 中的 install 方法
Vue.use(Vuex);
// 实例化容器容器:Vuex.Store
const store = new Vuex.Store({
state: {
num: 10
},
getters: {
// 根据商品数量计算总价格
getPrice(state) {
return state.num * 10
}
},
});
export default store;
在template
中,使用用 getters 方法 getPrice:
// src/App.vue
<template>
<div id="app">
商品数量: {{this.$store.state.num}} 个<br>
商品单价: 10 元<br>
订单金额: {{this.$store.getters.getPrice}} 元<br>
</div>
</template>
备注:由于 getters 具备计算属性特性,当依赖的 state 状态改变时,会触发更新;
5,mutation 的使用
在 vuex 中,通过 commit 提交 mutation 是更新状态的唯一方式;
mutation 方法:
- 第一个参数:state 状态对象;
- 第二个参数:payload 载荷,本次修改结果;
// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
num: 10
},
mutations: {
// 更新 num
changeNum(state, payload) {
state.num += payload;
}
}
});
export default store;
在 template
中,直接调用 commit 方法提交 mutation,同步更新状态:
// 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>
</div>
</template>
点击同步更新按钮,触发 mutation 方法,视图更新:
6,action 的使用
组件通过调用 dispatch 触发 action 执行异步请求返回结果数据,再通过 commit 提交 mutation 完成状态更新;
在 action 方法中:
- 可以继续调用 dispatch 触发 action;
- 可以多次调用 commit 进行状态提交;
备注:
- mutation 方法的目的是修改状态,所以第一个参数是 state 状态;
- action 方法需要将结果提交到 mutation,所以第一个参数是 store(store 中包含了 commit 方法)
// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
num: 10
},
mutations: {
changeNum(state, payload) {
state.num += payload;
}
},
// action作用:执行异步操作,并将结果提交给 mutations
actions: {
changeNum({ commit }, payload) {
setTimeout(() => { // 模拟异步
commit('changeNum', payload)
}, 1000);
}
}
});
export default store;
备注:这里使用 setTimeout 模拟异步操作;
在 template
中,直接调用 dispatch 方法触发 action,异步更新状态:
// 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>
点击异步更新按钮,1 秒后,视图更新:
以上,就是 vuex 几个核心概念的基本用法;
四,结尾
本篇,介绍了 vuex 的基本用法,主要包含以下几个点:
- vuex 项目创建;
- vuex 工作流程介绍;
- vuex 的基本使用介绍;
下一篇,介绍 vuex 的 install 插件安装逻辑;
维护日志
-
20210918:
- 优化文章描述,添加了部分代码的意图与注释;