Vuex 学习备忘

vuex 是一个存数据的容器,在全局都可以访问,用于解决跨多层/多个组件之间的数据交互问题。注意!本文为个人备忘,是 vuex 官方教程 的学习总结,通过阅读本文来学习 vuex 可能会产生疑惑。主要内容如下:

  • 注册 vuex
  • 概念 state - 数据的存放场所
  • 概念 getters - 数据的 get 访问器
  • 概念 mutations - 数据的同步 set 访问器
  • 概念 actions - 数据的异步 set 访问器

注册 vuex

安装

yarn add vuex

注册

import Vuex from 'vuex'
Vue.use(Vuex)

新建

// 新建 store
const store = new Vuex.Store({
    state: {
        count: 0
    }
})
// 绑定到 vue 实例中
new Vue({
    router,
    store,
    render: h => h(App),
}).$mount('#app')

状态 state

vuex 将保存在自己内部的数据称为 状态,所有的操作都是围绕着处理”状态“进行的。vuex 为了节省代码量和高效的在计算属性中使用 vuex 而设计了mapSatate方法,详情见 这里。

新建

const store = new Vuex.Store({
    // vuex 将状态保存在 state 对象里
    state: {
        count: 0
    }
})

使用

// 组件内部的计算属性
computed: {
    count() {
        // 使用 $store 获取全局的 vuex 容器
        return this.$store.state.count
    }
},

访问器 getters

vuex 支持给状态设置 get 访问器,要写在 storegetters 属性里,用于访问状态时执行额外逻辑,可以在此封装常用方法,例如筛选或统计数量等。有两种使用方式,分别是带参数访问和不带参数访问。

不带参数访问

用于获取一些通用属性,例如获取状态长度等。访问器接受两个参数,参数1为该模块的状态state,第二个参数为该模块的所有访问器getters,可以通过第二个参数来使用其他getter。注意,该方法在使用时不能在后面加(),不然会报错。

// 定义
const store = new Vuex.Store({
    state: {
        todoList: [
            {id: 1, text: '第一条', done: true},
            {id: 2, text: '第二条', done: false},
        ]
    },
    getters: {
        getDoneTodo: (state, getters) => {
            return state.todoList.filter(todo => todo.done)
        }
    }
})
// 组件中调用
computed: {
    count() {
        // 直接使用访问器的名称
        return this.$store.getters.getDoneTodo
        // 这种会报错
        // return this.$store.getters.getDoneTodo()
    }
},

带参数访问

可以给访问器传递参数来进行查询,想要支持携带参数需要让 getter 返回一个方法:

// 定义
const store = new Vuex.Store({
    state: {
        todoList: [
            {id: 1, text: '第一条', done: true},
            {id: 2, text: '第二条', done: false},
        ]
    },
    getters: {
        // 根据 id 查询数据
        getTodo: state => id => {
            return state.todoList.find(todo => todo.id === id)
        }
    }
})
// 组件中调用
computed: {
    count() {
        return this.$store.getters.getTodo(2)
    }
}

同步setter访问器 mutations

mutations 是用于修改 state 的唯一手段,且其中只允许出现同步事务,因为无法追踪其状态,mutations 非常类似于事件,就连使用方法也和使用 $emit 发射事件很像。注意,mutations,提交的修改也是响应式的,所以需要遵守 vue 的响应式原则,例如 修改对象的一个属性不会触发响应,应使用 Vue.set()

mutations 接受两个参数,第一个参数是本模块的状态 state ,第二个参数则是 mutations 在调用时接受的参数。store.commit 方法也接受两个参数,第一个参数为访问器的名称,第二个参数为要传递的参数。commit() 也支持对象风格的提交方式,详情见 这里。

// 定义
const store = new Vuex.Store({
    state: {
        count: 0,
    },
    mutations: {
        // 将 count 加指定的值,increment 是自定义的访问器名称
        increment(state, payload) {
            state.count += payload.value
        }
    }
})
// 组件中调用
methods: {
    add() {
        // 使用 commit 方法”发射事件“,并传递参数
        this.$store.commit('increment', {
            value: 10
        })
    }
},

如果觉得用store.commit方法不够直观的话,vuex 提供了 mapMutations 方法来优化你的代码可读性

import { mapMutations } from 'vuex'

methods: {
    // 映射指定访问器,以便可以直接用 this.increment 访问
    ...mapMutations([ 'increment' ]),
    // 映射指定访问器,以便可以直接用 this.addNum 访问
    ...mapMutations({ addNum: 'increment' }),
    add() {
        // 这种写法
        this.increment({
            value: 10
        })
        // 等同于
        // this.$store.commit('increment', {
        //     value: 10
        // })
    }
}

异步set访问器 actions

actions 的写法几乎和上一节的 mutations 完全一样,而且也包含一个 mapActions,用法和上一节的 mapMutations 一样。而其区别有以下三点:

  • 注册 action 时接受的第一个参数为context对象,这个玩意跟整个 store 实例很像,不过他是当前模块的 "store"。
  • actions 通过 store.dispatch 方法触发,而不是 store.commit ,不过他们俩的具体用法是一样的。
  • actions 里可以包含异步操作,但是最终还是要通过使用 store.commit 来修改状态的。
// 定义
const store = new Vuex.Store({
    state: {
        count: 0,
    },
    // actions 最终还是要靠 mutations 修改数据
    mutations: {
        increment(state, payload) {
            state.count += payload.value
        }
    },
    actions: {
        // actions 里方法可以跟 mutations 同名
        // 因为第一个参数是整个 "store",所以可以通过解构取出其中的 commit 方法
        increment({ commit }, payload) {
            setTimeout(() => {
                commit('increment', payload)
            }, 1000)
        }
    }
})
// 组件中调用
methods: {
    add() {
        this.$store.dispatch('increment', {
            value: 10
        })
    }
},

可以在 action 里返回一个 Promise 来使得调用者继续处理:

// 定义
actions: {
    increment({ commit }, payload) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                commit('increment', payload)
                resolve()
            }, 1000)
        })
    }
}
// 调用
this.$store.dispatch('increment', {
    value: 10
}).then(() => {
    ...
})

你可能感兴趣的:(Vuex 学习备忘)