Vue的状态管理vuex使用方法详解(3)

// 在单独构建的版本中辅助函数为 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 函数返回的是一个对象。如何将它与局部计算属性混合使用呢?通常,需要使用一个工具函数将多个对象合并为一个,将最终对象传给 computed 属性。但是自从有了对象展开运算符,可以极大地简化写法:

computed: { localComputed () { /* ... */ }, // 使用对象展开运算符将此对象混入到外部对象中 ...mapState({ // ... }) }

组件仍然保有局部状态

使用 Vuex 并不意味着需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态

Getter

有时候需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:

computed: { doneTodosCount () { return this.$store.state.todos.filter(todo => todo.done).length } }

如果有多个组件需要用到此属性,要么复制这个函数,或者抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想

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) } } })

Getter 会暴露为 store.getters 对象:

store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]

Getter 也可以接受其他 getter 作为第二个参数:

getters: { // ... doneTodosCount: (state, getters) => { return getters.doneTodos.length } } store.getters.doneTodosCount // -> 1

可以很容易地在任何组件中使用它:

computed: { doneTodosCount () { return this.$store.getters.doneTodosCount } }

也可以通过让 getter 返回一个函数,来实现给 getter 传参。在对 store 里的数组进行查询时非常有用

getters: { // ... getTodoById: (state, getters) => (id) => { return state.todos.find(todo => todo.id === id) } } store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

如果箭头函数不好理解,翻译成普通函数如下

var getTodoById = function(state,getters){ return function(id){ return state.todos.find(function(todo){ return todo.id === id }) } } store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

mapGetters辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

import { mapGetters } from 'vuex' export default { // ... computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ]) } }

如果想将一个 getter 属性另取一个名字,使用对象形式:

mapGetters({ // 映射 `this.doneCount` 为 `store.getters.doneTodosCount` doneCount: 'doneTodosCount' })

mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // 变更状态 state.count++ } } })

不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,需要以相应的 type 调用 store.commit 方法:

store.commit('increment')

提交载荷(Payload)

可以向 store.commit 传入额外的参数,即 mutation 的 载荷(payload)

// ... mutations: { increment (state, n) { state.count += n } } store.commit('increment', 10)

在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读:

// ... mutations: { increment (state, payload) { state.count += payload.amount } } store.commit('increment', { amount: 10 })

对象风格的提交方式

提交 mutation 的另一种方式是直接使用包含 type 属性的对象

store.commit({ type: 'increment', amount: 10 })

当使用对象风格的提交方式,整个对象都作为载荷传给 mutation 函数,因此 handler 保持不变:

mutations: { increment (state, payload) { state.count += payload.amount } }

遵守响应规则

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/f8f12dac30a05367ae20732c62aad03a.html