1.安装
npm install --save vuex
2.使用
1.官方文档中说的在根组件注入store,个人在main.js中定义了store,结果不好使,后来发现是在src下新建一个store文件夹,然后新建index.js,在index.js中写入代码
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)const state = { count: 0, ...}const store = new Vuex.Store({ state, mutations: { handleFunctions() { // xxx } }});export default store复制代码
main.js
import store from './store'new Vue({ store, render: h => h(App),}).$mount('#app')复制代码
3.Vuex概念 —— State
Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态
computed: { count () { return this.$store.state.count }}复制代码
每当 this.$store.state.count
变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
mapState辅助函数
当一个组件需要多个状态时,需要为每一个状态都声明为计算属性,当然,优秀的程序猿是不会这样的做的,这样就用到了mapState
适用场景:组件需要多个状态
{
{ count }}{
{ countAlias }}{
{ countPlusLocalState }} // 在使用状态的组件中import { mapState } from 'vuex'export default { ... data() { return { localCount: 0 } } computed: mapState({ // 函数方式(传统) count: state => state.count, // 传入state子节点名称的字符串 countAlias: 'count', // 能够使用 `this` 获取局部状态(组件自己的状态),必须使用常规函数 countPlusLocalState (state) { return state.count + this.localCount } })}复制代码
上边的computed
等价于
computed: { count() { return this.$store.state.count; }, countAlias() { return this.$store.state.count; }, countPlusLocalState() { return this.$store.state.count + this.localCount; }}复制代码
当映射的计算属性的名称与 state
的子节点名称相同时,mapState
中传一个字符串数组
// src/store/index.jsconst state = { count: 0, countAlias: 1, ...}// 引用组件中computed: mapState([ 'count', 'countAlias'])等价于:computed: { count() { return this.$store.state.count; }, countAlias() { return this.$store.state.countAlias; }}复制代码
当computed
计算属性中既包含了state
状态,又包含了组件私有的计算属性时,可以使用对象扩展运算符
computed: { localCount() { // 组件私有计算属性 }, ...mapState({ // state状态收集 ... }) }复制代码
4.Vuex概念 —— Getter
适用场景:需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数
一般写法:
computed: { doneTodosCount () { return this.$store.state.todos.filter(todo => todo.done).length }}复制代码
短板:如果有多个组件需要用到此属性,要么复制这个函数,或者抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想
改进:
// src/store/index.jsconst store = new Vuex.Store({ state: { todos: [ {id: 1, text: '...', done: 1}, {id: 2, text: '...', done: 2} ] } getters: { doneTodos: state => { return state.todos.filter(todo => todo.done); }, // 将其他getter作为第二个参数 doneTodosCount: (state, getters) => { return getters.doneTodos.length }, // 返回一个函数 getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } }, mutations: { // ... }})复制代码
在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。也可以通过让 getter 返回一个函数,来实现给 getter 传参。在对 store 里的数组进行查询时非常有用
Getter接收state为其第一个函数,其他getter作为第二个函数。
getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果 在其他组件中使用
this.$store.getters.doneTodos;this.$store.getters.getTodoById(2);复制代码
mapGetters
辅助函数
mapGetters
辅助函数仅仅是将 store 中的 getter 映射到局部计算属性,使用同mapState
使用
import { mapGetters } from 'vuex';复制代码
5.Vuex概念 —— Mutation
在Vuex中更改状态的唯一方式是提交commit,this.$store.commit('increment')
,每个mutation都有一个事件类型(type) 和一个 回调函数(handler),状态的更改在回调函数中进行
const store = new Vuex.Store({ state: { // ... }, mutations: { increment (state){ // ... 这里的‘increment’即type,函数体为回调函数 } }})复制代码
可以在this.$store.commit
时传入额外的参数,如this.$store.commit('increment', 100)
,这个叫做mutation的载荷,大多情况下载荷是一个对象
// store/index.jsmutations: { increment (state, obj){ state.count += obj.num }}// xxx.vuethis.$store.commit('increment', { num: 100, name: 'a'})=> 提交方式2:对象提交方式,mutation的回调函数保持不变this.$store.commit({ type: 'increment', num: 100, name: 'a'})复制代码
注意事项:
Mutation必须是同步函数
mapMutations辅助函数
mapMutations
将组建的methods
映射为store.commit
调用
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')` }) }}复制代码