State:全局状态
1:通过在根实例中注册 store
选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store
访问到 而不是在每个vue模块导入inport store 方式
2:mapState
辅助函数帮助我们生成多个计算属性 写法computed:mapState({})
3:映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState
传一个字符串数组
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
4:对象展开运算符,直接合并computed原来的和现在的mapState
Getter:相当于store的计算属性
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) } } })
1:属性访问,this.$store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }],属于Vue响应系统组成部分,计算属性特征
2: Getter 也可以接受其他 getter 作为第二个参数:使用场景不是太清楚
doneTodosCount: (state, getters) => { return getters.doneTodos.length }
3:方法访问:你也可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。
4:mapGetters
辅助函数,将 store 中的 getter 映射到局部计算属性:使用方法同mapState,数组字符串、别名、扩展运算符
Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation,必须同步方式
1:提交载荷(Payload):传递多余的参数,
store.commit('increment', 10) 提交简单字符串
store.commit('increment', {
amount: 10
}) 提交对象
store.commit({
type: 'increment',
amount: 10
}) 类型和参数一起提交
2:Mutation 需遵守 Vue 的响应规则
先初始化,添加新的属性的set方式,重新赋值,对象扩展符使用
3:使用常量替代 Mutation 事件类型,新增一个存放类型的模块,
import Vuex from 'vuex' import { SOME_MUTATION } from './mutation-types' const store = new Vuex.Store({ state: { ... }, mutations: { // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名 [SOME_MUTATION] (state) { // mutate state } } })
4:在组件中提交 Mutation,
a:你可以在组件中使用 this.$store.commit('xxx')
提交 mutation,
b:或者使用 mapMutations
辅助函数将组件中的 methods 映射为 store.commit
调用(需要在根节点注入 store
)。
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')` }) } }
Action异步操作:
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,然后mutation去更改状态,而不是直接变更状态。
- Action 可以包含任意异步操作。
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } })
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
因此你可以调用context.commit
提交一个 mutation,或者通过context.state
和context.getters
来获取 state 和 getters
触发:
1:store.dispatch('increment')
2:负荷形式,类似mutations
3:按照对象方式分发
模拟购物车,多重 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) ) } }
4:组件中,this.$store.dispatch 可以在方法中进行mapActions 映射
import { mapActions } from 'vuex' export default { // ... methods: { ...mapActions([ 'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` // `mapActions` 也支持载荷: 'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')` }) } }
5;组合 Action
Action 通常是异步的,那么如何知道 action 什么时候结束呢?更重要的是,我们如何才能组合多个 action,以处理更加复杂的异步流程?
首先,你需要明白 store.dispatch
可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch
仍旧返回 Promise:
Module
const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } })
1:对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象
2:对于模块内部的 action,局部状态通过 context.state
暴露出来,根节点状态则为 context.rootState
:
3:对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:
项目结构;
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules
├── cart.js # 购物车模块
└── products.js # 产品模块
严格模式和发布模式
1:严格模式,调试模式使用
2:发布模式,关闭,避免影响性能
const store = new Vuex.Store({ // ... strict: process.env.NODE_ENV !== 'production' })