关于vue.js:vuex

76次阅读

共计 4454 个字符,预计需要花费 12 分钟才能阅读完成。

vuex

参考:https://vuex.vuejs.org/zh/

装置

npm run vuex --save

生产依赖

简略应用

三局部

  1. 显示的应用 Vue.use() 来应用 vuex

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
  2. 生成 store 实例

    const store = new Vuex.Store({
        state: {count: 0},
        getters: {getterCount(state) {return state.count + 1}
        },
        mutations: {changeCount(state, payload) {state.count = payload.count}
        },
        actions: {changeCount({ commit}) {commit('changeCount')
            }
        }
    })
  3. 应用, 通过 store.state 来获取对象,通过 store.commit 来触发状态变变更

    store.commit('changeCount') // 触发 mutations
    store.dispatch('changeCount') // 散发 actions
    console.log(store.state.count) // -> 1
    console.log(stroe.getters.getterCount) // -> 2

下面步骤曾经能够应用 vuex 了,然而在组件中应用不不便,每在一个组件中应用都要进行导入,所以,Vuex 提供了一个从根组件向所有子组件,以 store 选项的形式“注入”该 store 的机制:

new Vue({
  el: '#app',
  store: store,
})

这个时候就能够间接在组件中通过 this.$store 应用 vuex 了

this.$store.commit('changeCount')
console.log(this.$store.state.count)

配合组件进行应用

下面说在根元素组件间注入 store 后,就能够在组件中通过一些辅助办法便捷的应用 store 了

State

间接通过 this.$store 拜访

computed: {count() {return this.$store.state.count}
}

通过辅助函数 mapState, mapState 返回值是一个对象

import {mapState} from 'vuex'

// 对象语法
computed: mapState({
    // 箭头函数
    count: state => state.count,
    // 字符串
    count: 'count',
    // 想要应用 this 的时候,只能应用惯例函数
    countAndThis(state) {return state.count + this.localCount}
})

// 数组语法
computed: mapState(['count'])

// 最终写法,用开展运算符,能够跟原生 computed 一起存在了

computed: {localCount() {return 1},
    ...mapState({countAndThis(state) {return state.count + this.localCount}
    })
}

个别都是放在 computed 属性中,不能放在 data 中,因为不会触发更新,也能够间接应用,会更新,然而不晓得会有什么其余问题不,所以不必思考那么多,间接放在 computed 属性里最好。

Getter

定义

getters: {
    // 返回一个值
    getterCount(state) {return state.count + 1}
    // 返回一个办法,能够从内部传值进来参加计算
    countMoreOut: state => count => state.count + count
}

用法跟 state 一样,不过辅助办法换成 mapGetters

Mutation

定义

mutations: {changeCount(state, payload) {state.count = payload.count},
    // 减少新对象的时候,要这样减少,要不然能够没用
    addKeys(state, payload) {state.obj = { ...state.obj, newProp: payload.newProp}
    }

}

提交格调,单值时用形式二好,多值时用形式一,但为了保障对立,对立用形式一好一些

// 形式一
store.commit('changeCount', {count: 10})
// 形式二,对象格调的提交形式
store.commit({
    type: 'changeCount',
    count: 10
})

辅助函数,mapMutations

import {mapMutations} from 'vuex'

methods: {
    // 对象传参
    ...mapMutions({changeCount:'changeCount'}),
    // 数组传参
    ...mapMutations(['changeCount'])
}

Action

action 里能够进行异步操作

定义:

actions: {changeCount({ commit}) {commmit('changeCount')
    }
}

应用办法跟 mutation 一样,不过,触发办法变成了 dispatch,辅助办法变成了 mapActions

Module

当我的项目比拟大的时候,能够思考将 store 宰割成模块,每个模块都领有本人的 state,mutation,action,getter,同时能够嵌套。

定义:

// rootGetters 要开启命名空间才有用
const login = {
    state: {count},
    getters: {getterCount(state, getters, rootState, rootGetters) {return state.count + 1}
    },
    mutations: {changeCount(state, payload) {state.count = payload.count}
    },
    actions: {changeCount({ state, getters, commit, dispatch, rootState, rootGetters}, payload) {commit('changeCount')
        }
    }
}

const store = new Vuex.Store({
    modules: {login}
})

命名空间

命名空间间默认是不开启的,模块外部的 action、mutation 和 getter 是注册在全局命名空间的,state 是部分的,当开启命名空间后,当模块被注册后,它的所有 getter、action 及 mutation 都会主动依据模块注册的门路调整命名。

开启

const login = {
    namespaced: true, // 开启命名空间
    state: {count},
    getters: {getterCount(state) {return state.count + 1}
    },
    mutations: {changeCount(state, payload) {state.count = payload.count}
    },
    actions: {changeCount({ commit}) {commit('changeCount')
        }
    }
}

const store = new Vuex.Store({
    modules: {login}
})

辅助办法取值的变动

办法一, 在原来的根底上把门路扩大,这种状况就不能用数组语法简写了

import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'

computed: {
    ...mapState({count: state.login.count}),
    ...mapGetters({getterCount: 'login/getterCount'})
}

methods: {
    ...mapMutations({changeCount: 'login/changeCount'}),
    ...mapActions({changeCount: 'login/changeCount'}),
}

办法二是在办法一的根底上把多余门路当成一个参数传给辅助办法

import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'

computed: {
    ...mapState('login', {count: state.count}),
    ...mapGetters('login', {getterCount: 'getterCount'})
}

methods: {
    ...mapMutations('login', {changeCount: 'changeCount'}),
    ...mapActions('login', {changeCount: 'changeCount'}),
}

办法三是应用 createNamespacedHelpers 创立基于某个命名空间辅助函数


import {createNamespacedHelpers} from 'vuex'
const {mapState, mapGetters, mapMutations, mapActions} = createNamespacedHelpers('login')

computed: {
    ...mapState({count: state.count}),
    ...mapGetters({getterCount: 'getterCount'})
}

methods: {
    ...mapMutations({changeCount: 'changeCount'}),
    ...mapActions({changeCount: 'changeCount'}),
}

vuex 进阶

插件

这个性能感觉不太可能用的到,反正至今为止还没须要用到过,这个选项会把每次 mutation 的钩子裸露进去,你能够生成 state 快照,比拟 mutation 前后 state 的区别,或者针对某个 mutation 做非凡解决

严格模式

开启

const store = new Vuex.Store({
    strict: true,
    // ...
})

在严格模式下,产生 state 状态变更不是由 mutation 函数引起的,都会报错,严格模式会深度监测状态树,在生产环境下要敞开

const store = new Vuex.Store({
    strict: process.env.NODE_DEV !== 'production',
    // ...
})

表单解决

在严格模式下,如果 input 绑定了 vuex.state 的值,当 input 输出的时候,会间接去批改 state 的值,因为不是由 mutation 去批改,会报错。所以的药做一些非凡解决

<input v-model="message">
// ...
computed: {
  message: {get () {return this.$store.state.obj.message},
    set (value) {this.$store.commit('updateMessage', value)
    }
  }
}

正文完
 0