推荐: ------ Vuex官方文档 -----
- Vuex是什么
Vuex是一个专门为Vue.js应用程序开发的状态管理模式.
简单来说: 应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏
● 多个视图依赖于同一状态
● 来自不同视图的行为需要变更同一状态
即Vuex提供了管理多个视图能够使用的共享状态 - 基本使用
每一个Vuex应用的核心就是store(仓库)
“store” 基本就是一个容器,它包含着你的应用中大部分的状态
Vuex和单纯的全局对象有一下两点不同:
(1) Vuex的状态存储是响应式的. 当Vue组件从store中读取状态的时候,若store中的状态发生变化,name相应的组件也会相应的得到高效更新
(2) 不能直接改变store中的状态. 改变store中的状态的唯一途径就是提交(commit)mutation. 这样使得我们可以方便的跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好的了解我们的应用
------------ 基本实例 -----------
new Vue({
el: "#app",
store
})
store 文件夹中的index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = new Vuex.Store({
// 1. store 中状态state
state: {
count: 0
},
// 2. 通过mutation实现state中的状态变更
mutation: {
// 第一参数传入state
increment(state) {
state.count++
}
}
})
从组件中通过store.state 获取状态对象,通过store.commit 方法触发状态变更
<script>
export default {
data() {
return {
// 本组件count 中绑定store中count
count: this.$store.state.count
}
},
methods: {
increment() {
this.$store.commit('increment')
console.log(this.count) // 1
}
},
}
</script>
核心概念
State
const store = new Vuex.Store({
state: {
count: 1
}
})
组件中访问
this.$store.state.count
Getters
getters可以认为是store中的计算属性,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖发生了改变才会被重新计算
Getter接受state作为其第一个参数
const store = new Vuex.Store({
state: {
todos: [
{
id: 1, text: '..', done: true},
{
id: 2, text: '..', done: false}
]
},
getters: {
doneTodos: state => {
// filter: 迭代数组,过滤出符合条件的数组返回一个新的数组
return state.todos.filter(todo => todo.done)
}
}
})
通过属性访问
Getter 会暴露为 store.getters 对象.可以以属性形式访问这些值
this.$store.getters.doneTodos // [{
id: 1, text: '..', done: true}]
Getter 也可以接受其他getter作为第二个参数:
getters: {
doneTodosCount: (state,getters) => {
return getters.doneTodos.length
}
}
this.store.getters.doneTodosCount // 1
注意: getter 在通过属性访问时是作为Vue的响应式系统的一部分缓存其中的
通过方法访问
你也可以通过让getter返回一个函数,来实现getter传参
getters: {
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
this.$store.getters.getTodoById(2) // {
id: 2, text: '..', done: false}
注意: getter在通过方法访问时,每次都会去进行调用,而不会缓存结果
Mutations
更改Vuex的store中的状态唯一方法就是提交mutation
每个mutation都有一个字符串的时间类型和一个回调函数
const store = new Vuex.Store({
state: {
count: 1
},
mutation: {
increment(state) {
//变更状态
state.count++
}
}
})
调用方法
this.$store.commit('increment')
提交载荷(Payload)
可以向store.commit 传入额外的参数,即mutation 的载荷(payload)
//...
mutations: {
increment(state, payload) {
state.count += payload.amount
}
}
this.$store.commit('increment', {
amount: 10
})
Mutation 需遵守Vue 的响应规则
Vuex中mutation的一些注意事项:
(1) 最好提前在store中初始化好所有所需属性
(2) mutation必须是同步函数
(3) 当需要在对象上添加新属性时,应该
使用 Vue.set(obj, ‘newProp’, 123),或者
(4) 以新对象替换老对象.例如利用对象展开运算符
//...
state: {
obj: {
name: 'lzy',
age: 17
}
}
}
state.obj = {
...state.obj, newProp: 123}
console.log(state.obj) // {
name: 'lzy', age: 17, newProp: 123}
/**
对象展开运算符(...)
可以将一个数组或者对象进行展开
例如: let obj = {
x:1 , y:2}
let aa = {
...obj, z: 3} // {
x:1 , y:2, z:3}
let obj2 = [1,2,3]
console.log(..obj) // 1 2 3
**/
mapMutations 辅助函数映射
import {
mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
Actions
Action类似于mutation,不同在于
● Action提交的是mutation,而不是直接变更状态
● Action可以包含任意一部操作
基本案例
const store = new Vuex.Store({
state: {
count: 0
},
mutation: {
increment (state) {
state.count++
}
},
actions: {
incrementAsync ({
commit }) {
setTimeOut(() => {
commit('increment')
},1000)
}
}
})
在组件中分发Action
在组件中使用this.$store.dispath(‘xxx’)分发action
或者使用mapAction 辅助函数将组件的method 映射为 store.dispath调用
import {
mapAction } from 'vuex'
export default {
//...
method: {
// 辅助函数映射调用
...mapActions({
add: 'increment' // 将`this.add()` 映射为`this.$store.dispatch('incrementAsync')`
})
// 直接调用
addAction() {
this.$store.dispatch('incrementAsync')
},
}
}
Modules
Vuex允许我们将store 分割成模块(Module)
每一个模块拥有自己的state,mutation,action.getter甚至嵌套子模块
const moduleA = {
state: () => ({
name: 'lzy',
count: 0
}),
mutations: {
increment (state) {
//这里'state'对象是模块的局部状态
state.count++
}
},
actions: {
... },
getters: {
sumWithRootCount(state, getters, rootState) {
// rootState根节点状态作为第三个参数暴露出来
return state.count + rootState.count
}
}
const moduleB = {
state: () => ({
...}),
mutations: {
...},
actions: {
...}
}
const store = new Vuex.Store({
state: {
count
},
modules: {
a: moduleA,
b: moduleB
}
})
在组件中调用module状态
// moduleA中的状态
this.$store.state.a.name