Open Easay opened 3 years ago
Vuex的store
中状态改变的唯一方法是提交mutation
,类似于事件:每个mutation
都有一个字符串的事件类型和一个回调函数。该回调函数是实际进行状态更改的地方,并且它会接受state
作为第一个参数:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
⚠️:不能直接调用mutation handler
,这个选项更像是事件注册:“当触发一个类型为increment
的mutation
时,调用此函数”。
store.commit('increment')
可以向store.commit
传入额外的参数,就是mutation
的载荷(payload):
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
🌟 多数情况下,载荷是一个对象。
// ...
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 10
})
store.commit({
type: 'increment',
amount: 10
})
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
1.最好提前在store中初始化好所有所需的属性; 2.当需要在对象上添加新属性时,应该:
Vue.set( obj, 'newProp', 123 )
state.obj = { ...state.obj, newProp: 123 }
// 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必须是同步函数
在组件中提交:this.$store.commit('xxx')
,或者使用Mutation的辅助函数mapMutations。可以直接将method中的方法映射成mutation使用。
import { mapMutations } from 'vuex'
export default {
method: {
...mapMutations([
'increment',
'incrementBy'
]),
...mapMutations({
add: 'increment'
})
}
}
Action
类似Mutation
,不同之处在于:
Action
用来提交Mutation
,而不是直接修改状态;Action
可以包含任意异步操作。Action
函数接受一个与store
实例具有相同方法和属性的context
对象。因此,可以按下面方式使用context
替代store
:
context.commit()
context.getters
context.state
可以使用参数结构简化:
actions: {
increment ({ commit }) {
commit('increment')
}
}
store.dispatch('increment')
可以在action内部执行异步操作:
actions: {
incrementAsync ({ commit }) {
setTimeout(()=>{
commit('increment')
}, 1000)
}
}
actions: {
checkout({ commit, state }, products) {
// 备份当前购物车的物品
const savedCartItems = [...state.cart.added]
// 发出结账请求,然后清空购物车
commit(types.CHECKOUT_REQUEST)
// 购物API接受一个成功回调和一个失败回调
shop.buyProducts(
products,
// 成功操作
() => commit(types.CHECKOUT_SUCCESS),
// 失败操作
() => commit(types.CHECKOUT_FAILURE, savedCartItems)
)
}
}
当应用非常复杂时,store对象可能变得相当臃肿,为了解决以上问题,vuex允许将store分成模块。每个模块拥有自己的state等内容。
const moduleA = {
state: () => ({
count: 0
}),
mutations: {
increment (state) {
// 这里的 `state` 对象是模块的局部状态
state.count++
}
},
getters: {
// 根节点状态会作为第三个参数暴露
doubleCount (state, getters, rootState) {
return state.count * 2
}
},
// 局部状态通过context.state暴露,根节点的状态为context.rootState
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的。
可以通过添加namespaced: true
的方式使其成为带命名空间的模块。
什么是Vuex?
Vuex是一个专门为vue.js应用程序开发的状态管理模式。采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
一、开始
每个Vuex应用的核心是一个store(仓库)。"store"是一个容器,包含着应用中的大部分状态。
与单纯的全局对象不同
mutation
.🌰:一个简单的计数应用
要想在vue组件中访问
this.$store
,需要为Vue实例提供创建好的store。二、State
Vuex使用单一状态树。用一个对象就包含全部的应用层级状态。每个应用仅包含一个store实例。存储在Vuex中的数据和Vue实例中的data遵循相同的规则。
在vue组件中获得vuex状态 最简单的方法是使用计算属性返回某个状态:
这种模式导致组件依赖全局状态单例。 Vuex通过
store
选项,提供了一种机制将状态从根组件“注入”到每个子组件中。通过在根实例中注册store,会将store注入到根组件下的所有子组件中。且子组件都能通过this.$store
访问到。三、mapState辅助函数
当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用
mapState
辅助函数帮助我们生成计算属性。四、Getter
帮助我们从store中的state中派生出一些状态,例如对列表进行过滤并计数:
vuex允许我们在store中定义
getter
,接受state
作为其第一个参数:通过属性访问
Getter会被暴露为
store.getters
对象,可以以属性的形式访问这些值:Getter可以接受其他getter作为第二个参数:
通过方法访问
可以通过让getter返回一个函数,来实现给getter传参。在对store里的数组进行查询时非常有用。
两者区别
getter
在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的;getter
在通过方法访问时,每次都会去进行调用,而不会缓存结果;五、mapGetters辅助函数