vuex 从0到1
vuex 从0到1
利用 vue-cli 快速搭建一个项目, 记录了 vuex 的 一些操作
项目初始化
vue init webpack router-router
# 使用 webpack 作为打包工具
# 需要安装 vue-router
# 暂时不需要单元测试等工具
# 使用 npm 进行依赖的管理
# 可是选择不安装依赖, 然后手动使用 cnpm 进行依赖安装
一些配置的修改
修改 /config/index.js中的配置项, 使得在 npm run dev 的时候自动打开浏览器.
- autoOpenBrowser: false,
+ autoOpenBrowser: true
编译过程
# install dependencies
cnpm install
# serve with hot reload at localhost:8080
npm run dev
背景介绍
对于非父子组件之间的通信, 最容易想到的是 Bus(中央事件总线)的方法, 用来触发和接收时间, 从而达到通信的目的. 而Vuex作为一个 Vue 的插件, 它的设计也是为了解决这个问题.
一个组件可以分为数据(model)和视图(view), 数据更新时, 视图也会自动更新. 在视图中可以绑定一些时间, 它们触发 methods 里的一些方法, 从而可以改变数据, 更新视图. 这是一个组件的基本运行模式.
而 Vuex 的出现, 能够非常优雅和高效的进行状态管理.
准备工作
安装 vuex
cnpm i -D vuex
在/src/store/index.js 中引入vuex 并且加载插件, 进行简单的配置.
import Vue from 'vue'
import Vuex from 'vuex'
// load the plugin
Vue.use(Vuex)
var store = new Vuex.Store({
})
export default store
在/src/App.vue中将图片内容注释掉
在 src/main.js 中引入/src/store/index.js 并且注册到视图模型中
基本用法
store 包含了应用的数据(状态)和操作过程. Vuex 中的数据也是响应式的, 只要 store 中的数据发生改变, 视图也就会立即发生改变.
数据保存在 state 字段内. 比如现在打算实现一个简单的计数器的业务
state 字段的内容.
var state = {
count: 0
}
同时, 新建一个 index.vue 的组件(/src/component/index.vue), 使用store实例读取 Vuex 管理的状态.
此时, 在组件内, 来自 store 的数据并不能直接手动改变, 改变 store 中的数据的唯一途径就是显式地提交 mutations.
mutations 也是 store 中的一个字段, 用来直接修改 state 中的数据, 需要接受一个参数 state.
var mutations = {
increment (state) {
state.count++
},
decrement (state) {
state.count--
}
}
mutations 还能接收第二个参数, 可以是数字, 字符串和对象类型.
var mutations = {
increment (state, n = 1) {
state.count += n
},
decrement (state, n = 1) {
state.count -= n
}
}
// 当一个参数不够时, 可以传入对象, 无限扩展
提交 mutations 的另一种方法是传入含有type字段的对象
在 src/store/index.js中修改 mutations 字段
decrement (state, params) {
state.count -= params.num
}
在 src/component/index.vue 中修改提交 mutations 的方法
handleReduce () {
// this.$store.commit('decrement', this.randomNum)
this.$store.commit({
type: 'decrement',
n: this.randomNum
})
this.changeNum()
}
在 mutations 中尽量不要异步操作数据, 因为在组件 commit 之后, 数据不能立即发生改变, 而且不知道什么时候才会发生改变.
高级用法
Vuex 主要有以下三种高级用法, getters, actions, modules
getters
getters 相当于 Vuex 的计算属性, 也是 store 的一个字段
比如, 可以有以下的例子.
首先, 现在 state 中增加以下的数据.
var state = {
count: 0,
+ list: [1, 43, 9, 5, 8, 32, 1, -1, 2, 13]
}
然后, 设置 getters 字段.
var getters = {
filteredList: state => {
return state.list.filter(value => value < 10)
}
}
这时候, 在组件中, 就可以访问 getters 字段中的值了
this.$store.getters.filteredList
同时, getters 不仅可以依赖state, 也能依赖其它的 getters.e.g.
var getters = {
filteredList: state => {
return state.list.filter(value => value < 10)
},
sortedAndFilteredList: (state, getters) => {
return getters.filteredList.sort((a, b) => {
if (a > b) {
return 1
} else if (a < b) {
return -1
} else {
return 0
}
})
}
}
其中, sortedAndFilteredList 依赖于 filteredList
actions
actions 字段主要处理的是业务逻辑, 比如, 在 mutations 并不建议使用异步操作, 但是异步操作可以在 actions 字段中执行, 通过 dispatch 来分发 actions (触发 mutations). e.g.
var actions = {
increment (context) {
context.commit('increment')
}
}
再比如, 可以在actions字段中, 增加异步的操作. e.g.
{
asnycIncrement (context) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('increment')
resolve()
}, 1000)
})
}
}
然后, 可以在组件中通过分发 actions
this.$store.dispatch('increment')
对
actions和mutations稍加总结, 不难得出, 所有设计改变数据的, 就用mutations, 存在业务逻辑的, 就用actions
modules
modules 字段的作用是将 store 分割到不同的模块. 当项目足够大的时候, store 里的 state, getters, mutations, actions会非常多, 都放在一个 js 文件中显得不是特别的友好, 使用 modules 能够将它们分割到不同的文件中. 每个 modules 都有自己的 state, getters, modules, actions, 并且可以多层嵌套. e.g.
// moduleA
const moduleA = {
state: {...},
mutations: {...},
getters: {...},
actions: {...}
}
// moduleB
const moduleB = {
state: {...},
mutations: {...},
getters: {...},
actions: {...}
}
// 实例化 store
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
此时,
store.state.a // moduleA 的状态
store.sate.b // moduleB 的状态
module 的 mutations 和 getters 接收的第一个参数都是当前模块的状态. 在 actions 和 getters 中还能接收一个参数 rootState 来访问根节点的状态. 比如, getters 的第三个参数
const moduleA = {
state: {
count: 0
},
getters: {
sumCount (state, getters, rootState) {
return rootState.count + state.count
}
}
}
浙公网安备 33010602011771号