Vuex
最简单的store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
count:3
},
mutations:{
increment(state){
state.count++;
}
}
})
store.commit('increment');
console.log(store.state.count);//4
State:单一状态树、唯一数据源、与Vue实例中的data遵循相同的规则、和模块化不冲突
1、如何在 Vue 组件中展示状态呢?
由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态;
每当store.state.count
变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
1.1 计算属性
// 创建一个 Counter 组件
const Counter = {
template: `<div>{{ count }}</div>`,
computed: {
count () {
return store.state.count
}
}
}
然而,这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态。
1.2 Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)
)
const app = new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
components: { Counter },
template: `
<div class="app">
<counter></counter>
</div>
`
})
mapState
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
对象展开运算符(…):将…mapState与外部对象放在一起
不是所有的状态都需要放到Vuex,有的明显是局部的状态就放到单个的组件中。
Getter
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
Getter 接受 state 作为其第一个参数:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
怎么访问Getters?
1、通过属性访问
Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值store.getters.doneTodos
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
todos: [{
id: 1,
text: '...',
done: true
},
{
id: 2,
text: '...',
done: false
}
]
},
getters: {//vuex中的“计算属性”
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
},
mutations: {
}
})
console.log(store.getters.doneTodos)
计算过滤处理的数组长度
getters: {//vuex中的“计算属性”
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
},
console.log(store.getters.doneTodosCount)
注意:getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的
通过方法访问
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
注意,getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
mapGetters
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
import { mapGetters } from 'vuex'
mutations
- Mutation 需遵守 Vue 的响应规则
- 使用常量替代mutation的事件类型
- Mutation 必须是同步函数
- 在组件中提交 Mutation
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 3,
},
mutations: {
increment(state) {
state.count++;
},
incrementByN(state,n){
state.count+=n
}
}
});
store.commit('increment');
console.log(store.state.count);//4
store.commit('incrementByN',10);
console.log(store.state.count);//14
提交载荷(Payload)
incrementByN(state,n){
state.count+=n
}
注意:通常情况下,载荷是一个对象,可以包含多个字段。
.....
incrementByOBJ(state,payload){
state.count+=payload.amount
}
......
store.commit('incrementByN',{amount:5});//可以使用
//一般情况下如下书写commit:对象风格的提交方式
store.commit({
type:'incrementByOBJ',
amount:20
});
.....
const store = new Vuex.Store({
state: {
obj:{},
}
})
//当需要在对象上添加新属性时
Vue.set(store.state.obj, 'newProp', 123)
console.log(store.state);
//以新对象替换老对象
store.state.obj = { ...store.state.obj, newProp: 789 }
console.log(store.state);//
规则2:使用常量替代mutation的类型
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import { SOME_MUTATION } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
[SOME_MUTATION] (state) {
// mutate state
}
}
})
mutation必须是同步函数,异步逻辑都应该封装到 action 里面
someMutation (state) {
api.callAsyncMethod(() => {
state.count++
})
}
在组件中提交mutation
更多:
1、Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数:
const myPlugin = store => {
// 当 store 初始化后调用
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用
// mutation 的格式为 { type, payload }
})
}
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
函数说明:
store.subscribe: subscribe,调用此方法返回的函数可停止订阅。》??在vue内声明一个变量,用来接住subscribe返回的函数,然后在beforeDestroy中调用其返回的函数即可
api.callAsyncMethod:api异步执行函数
2、如何将状态和状态变更事件分布到各个子模块中?
推荐
vue#data
Array的filter方法
vuex学习推荐
更多冷门知识推荐
vue构造函数(根实例化时和组件实例对象选项)参数:选项详解