首先通过import
引入vuex
,然后通过Vue.use(Vuex)
加载,最后创建Vuex
实例并导出。
可以理解为vue组件中的data
,在其中定义的变量可以在各个组件中使用。
...
state: {
name: 'anni'
},
...
组件中使用:
<template>
<div>{{ name }}</div>
</template>
<script>
export default {
computed: {
name () {
return this.$store.state.name;
}
}
}
</script>
使用module中定义的state变量
modules: {
user: {
state: {
name: 'tom'
}
}
}
computed: {
modulesName () {
// 加上模块名
return this.$store.state.user.name;
}
}
<template>
<div>{{ name }}</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed: {
// 传入数组
...mapState([
'name'
])
// 也可传入对象 state为vuex中的state
...mapState({
name: state => state.name
})
// 访问模块中的变量
...mapState({
modulesName: state => state.user.name
}),
}
}
</script>
modules: {
user: {
// 开启命名空间
namespaced: true,
state: {
name: 'tom'
}
}
}
// 模块名当作第一个参数传入
...mapState('user',{
// 此时state直接为user模块中的state,使用时便不需要在点出模块名
modulesName: state => state.name
}),
或者
import { createNamespacedHelpers } from 'vuex';
const { mapState } = createNamespacedHelpers('user');
export default {
computed: {
...mapState({
modulesName: state => state.name
})
}
}
相当于组件中的计算属性。
getters:{
// state为同级下的vuex state
allName: (state) => state.name + 'jack'
},
<template>
<div>
<div>{{ allName }}</div>
</div>
</template>
<script>
export default {
computed: {
allName () {
return this.$store.getters.allName
}
}
}
</script>
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters([
'allName'
])
}
}
getters:{
allName: (state) => state.name + 'jack'
},
modules: {
user: {
namespaced: true,
getters: {
modulesAllName: (state) => state.name + 'modules'
}
}
}
// 如果模块未开启命名空间可直接访问,注意各个模块和根getter中的名字不要重复,之后的matations和actions同。
...mapGetters([
'allName',
'modulesAllName'
])
// 如果开启了命名空间
...mapGetters('user', [
'modulesAllName'
])
// 或
...mapGetters({
modulesAllName: 'user/modulesAllName'
})
更改 Vuex
的 store
中的状态的唯一方法是提交 mutation
。
state: {
name: 'anni'
},
mutations: {
setName (state, params) {
state.name = params;
}
},
<template>
<div>
<p>{{ name }}</p>
<button @click="clickHandle">修改state值</button>
</div>
</template>
<script>
export default {
computed: {
name () {
return this.$store.state.name;
},
},
methods: {
clickHandle () {
// 参数为一个
this.$store.commit('setName', 'reset');
// 参数为多个
this.$store.commit('setName', {
name: 'reset',
name2: 'reset2'
});
// 对象写法
this.$store.commit({
type: 'setName',
name: 'reset'
});
}
}
}
当前state
中只有name
一个值,如果想新添变量
setNew (state) {
Vue.set(state, 'newParam', 123);
}
import { mapMutations } from 'vuex';
...
methods: {
...mapMutations([
'setName',
'setNew'
]),
clickHandle () {
this.setName('new name');
this.setNew();
}
}
modules: {
user: {
state: {
name: 'tom'
},
getters: {
modulesAllName: (state) => state.name + 'modules'
},
mutations: {
setModuleName (state, params) {
state.name = params;
}
}
}
}
// 如未开启模块命名空间,直接访问
...mapMutations([
'setModuleName'
]),
// 开启命名空间
...mapMutations('user', [
'setModuleName'
]),
clickHandle () {
this.setModuleName('new module name');
}
Action
类似于 mutation
,不同在于:
Action
提交的是 mutation
,而不是直接变更状态。Action
可以包含任意异步操作。// 模拟请求
const request = () => {
return new Promise((res, rej) => {
const err = null;
if (!err) res({code: '200', data: { name: 'new name' }});
else rej('错误!');
})
}
...
mutations: {
setName (state, params) {
state.name = params;
}
},
actions: {
getName ({ commit }) {
request().then((res) => {
commit('setName', res.data.name);
}).catch((err) => {
console.log(err);
})
}
},
import { mapActions } from 'vuex';
...
methods: {
...mapActions([
'getName'
]),
handleClick () {
this.$store.dispatch('getName');
// 或
this.getName();
}
}
modules: {
namespaced: true,
user: {
...
modules: {
namespaced: true,
childUser: {
actions: {
getModuleName ({ commit, state, rootState, dispatch }) {
...
}
},
}
}
}
}
// 如全部开启命名空间
...mapActions('user/childUser', [
'getModuleName'
])
modules: {
namespaced: true,
user: {
...
modules: {
namespaced: true,
childUser: {
actions: {
getModuleName ({ commit, state, rootState, dispatch }) {
commit: 用来调用当前模块mutation
state: 当前模块state
rootState: 根state
dispathc: 用来调用当前模块action
}
},
}
}
}
}
this.$store.registerModule('newModule', {
state: {
...
},
getters: {
...
}
...
})
// 给模块注册模块
this.$store.registerModule(['newModule', 'childModule'], {
...
})
Vuex
的 store
接受 plugins
选项,这个选项暴露出每次 mutation
的钩子。Vuex
插件就是一个函数,它接收 store
作为唯一参数。
// 持久化存储
const saveInlocal = store => {
// 当 store 初始化后调用
if (localStorage.state) store.replaceState(JSON.parse(localStorage.state));
store.subscribe((mutation, state) => {
// 每次 mutation 之后调用
// mutation 的格式为 { type, payload }
localStorage.state = JSON.stringify(state);
})
}
...
export default new Vuex.Store({
...
plugins: [
saveInlocal
]
})
开启严格模式,仅需在创建 store 的时候传入 strict: true:
const store = new Vuex.Store({
// ...
strict: true
})
在严格模式下,无论何时发生了状态变更且不是由 mutation
函数引起的,将会抛出错误。这能保证所有的状态变更都能被调试工具跟踪到。
不要在发布环境下启用严格模式!严格模式会深度监测状态树来检测不合规的状态变更——请确保在发布环境下关闭严格模式,以避免性能损失。
类似于插件,我们可以让构建工具来处理这种情况:
const store = new Vuex.Store({
// ...
strict: process.env.NODE_ENV !== 'production'
})
...
...
computed: {
...mapState({
name: state => state.name
}),
}
methods: {
...mapMutations([
'setName'
]),
handleInput (e) {
this.setName(e.target.value);
}
}
// 或
...
...
computed: {
name: {
get () {
return this.$store.state.name
},
set (val) {
this.setName(val)
}
}
},
methods: {
...mapMutations([
'setName'
]),
}