Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,而更改状态的惟一方法是提交mutation,例this.$store.commit('SET_VIDEO_PAUSE', video_pause
,SET_VIDEO_PAUSE
为mutation属性中定义的方法 。vue
解决两个问题vuex
当项目遇到如下两种场景时bash
使用mapState辅助函数, 利用对象展开运算符将state混入computed对象中异步
import {mapState} from 'vuex'
export default{
computed:{
...mapState(['price','number'])
}
}
复制代码
getter接收两个参数,第一个是state,第二个是getters(能够用来访问其余getter)。async
const store = new Vuex.Store({
state: {
price: 10,
number: 10,
discount: 0.7,
},
getters: {
total: state => {
return state.price * state.number
},
discountTotal: (state, getters) => {
return state.discount * getters.total
}
},
});
复制代码
而后在组件中能够用计算属性computed经过this.$store.getters.total
这样来访问这些派生转态。ide
computed: {
total() {
return this.$store.getters.total
},
discountTotal() {
return this.$store.getters.discountTotal
}
}
复制代码
经过让getter返回一个函数,来实现给getter传参。而后经过参数来进行判断从而获取state中知足要求的状态。函数
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
getTodoById: (state) => (id) =>{
return state.todos.find(todo => todo.id === id)
}
},
});
复制代码
而后在组件中能够用计算属性computed经过this.$store.getters.getTodoById(2)
这样来访问这些派生转态。ui
computed: {
getTodoById() {
return this.$store.getters.getTodoById
},
}
mounted(){
console.log(this.getTodoById(2).done)//false
}
复制代码
使用mapGetters辅助函数, 利用对象展开运算符将getter混入computed 对象中this
import {mapGetters} from 'vuex'
export default{
computed:{
...mapGetters(['total','discountTotal'])
}
}
复制代码
使用mapGetters辅助函数, 利用对象展开运算符将getter混入computed 对象中spa
import {mapGetters} from 'vuex'
export default{
computed:{
...mapGetters(
myTotal:'total',
myDiscountTotal:'discountTotal',
)
}
}
复制代码
首先要在mutations中注册一个mutation
const store = new Vuex.Store({
state: {
number: 10,
},
mutations: {
SET_NUMBER(state,data){
state.number=data;
}
},
});
复制代码
在组件中使用this.$store.commit
提交mutation,改变number
this.$store.commit('SET_NUMBER',10)
复制代码
使用mapMutations辅助函数,在组件中这么使用
methods:{
...mapMutations({
setNumber:'SET_NUMBER',
})
}
复制代码
而后调用this.setNumber(10)
至关调用this.$store.commit('SET_NUMBER',10)
this.$store.dispatch('ACTION_NAME',data)
来提交。mutation是用this.$store.commit('SET_NUMBER',10)
来提交。{
state, // 等同于 `store.state`,若在模块中则为局部状态
rootState, // 等同于 `store.state`,只存在于模块中
commit, // 等同于 `store.commit`
dispatch, // 等同于 `store.dispatch`
getters, // 等同于 `store.getters`
rootGetters // 等同于 `store.getters`,只存在于模块中
}
复制代码
第二参数均可以接收外部提交时传来的参数。 this.$store.dispatch('ACTION_NAME',data)
和this.$store.commit('SET_NUMBER',10)
使用mapActions辅助函数,在组件中这么使用
methods:{
...mapActions({
setNumber:'SET_NUMBER',
})
}
复制代码
而后调用this.setNumber(10)
至关调用this.$store.dispatch('SET_NUMBER',10)
在action函数中返回Promise,而后再提交时候用then处理
actions:{
SET_NUMBER_A({commit},data){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
commit('SET_NUMBER',10)
},2000)
}
)
}
}
this.$store.dispatch('SET_NUMBER_A').then(() => {
// ...
})
复制代码
利用ES6的async
和await
来实现。
actions:{
async actionA({commit}){
//...
},
async actionB({dispatch}){
await dispatch ('actionA')//等待actionA完成
// ...
}
}
复制代码
有,由于使用单一状态树,应用的全部状态会集中到一个比较大的对象。当应用变得很是复杂时,store 对象就有可能变得至关臃肿。因此将 store 分割成模块(module)。每一个模块拥有本身的 state、mutations、actions、getters,甚至是嵌套子模块,从上至下进行一样方式的分割。
在module文件新建moduleA.js和moduleB.js文件。在文件中写入
const state={
//...
}
const getters={
//...
}
const mutations={
//...
}
const actions={
//...
}
export default{
state,
getters,
mutations,
actions
}
复制代码
而后再index.js引入模块
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import moduleA from './module/moduleA'
import moduleB from './module/moduleB'
const store = new Vuex.Store({
modules:{
moduleA,
moduleB
}
})
export default store
复制代码
context.rootState
访问到全局的state,context.rootGetters
访问到全局的getter。this.$store.getters
和this.$store.state
来访问模块中的getter和state。this.$store.commit('mutationA',data)
提交模块中的mutation。this.$store.dispatch('actionA,data')
提交模块中的action。默认状况下,模块内部的action、mutation和getter是注册在全局命名空间,若是多个模块中action、mutation的命名是同样的,那么提交mutation、action时,将会触发全部模块中命名相同的mutation、action。
这样有太多的耦合,若是要使你的模块具备更高的封装度和复用性,你能够经过添加namespaced: true
的方式使其成为带命名空间的模块。
export default{
namespaced: true,
state,
getters,
mutations,
actions
}
复制代码
将 { root: true } 做为第三参数传给 dispatch 或 commit 便可。
this.$store.dispatch('actionA', null, { root: true })
this.$store.commit('mutationA', null, { root: true })
复制代码
actions: {
actionA: {
root: true,
handler (context, data) { ... }
}
}
复制代码
this.$store.commit('moduleA/mutationA',data)
复制代码
首先使用createNamespacedHelpers
建立基于某个命名空间辅助函数
import { createNamespacedHelpers } from 'vuex';
const { mapState, mapActions } = createNamespacedHelpers('moduleA');
export default {
computed: {
// 在 `module/moduleA` 中查找
...mapState({
a: state => state.a,
b: state => state.b
})
},
methods: {
// 在 `module/moduleA` 中查找
...mapActions([
'actionA',
'actionB'
])
}
}
复制代码
Vuex插件就是一个函数,它接收 store 做为惟一参数。在Vuex.Store构造器选项plugins引入。 在store/plugin.js文件中写入
export default function createPlugin(param){
return store =>{
//...
}
}
复制代码
而后在store/index.js文件中写入
import createPlugin from './plugin.js'
const plugin = createPlugin()
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
复制代码
subscribe
监听组件中提交mutationsubscribeAction
监听组件中提交action 在store/plugin.js文件中写入export default function createPlugin(param) {
return store => {
store.subscribe((mutation, state) => {
console.log(mutation.type)//是那个mutation
console.log(mutation.payload)
console.log(state)
})
// store.subscribeAction((action, state) => {
// console.log(action.type)//是那个action
// console.log(action.payload)//提交action的参数
// })
store.subscribeAction({
before: (action, state) => {//提交action以前
console.log(`before action ${action.type}`)
},
after: (action, state) => {//提交action以后
console.log(`after action ${action.type}`)
}
})
}
}
复制代码
而后在store/index.js文件中写入
import createPlugin from './plugin.js'
const plugin = createPlugin()
const store = new Vuex.Store({
// ...
plugins: [myPlugin]
})
复制代码
须要经过computed计算属性来转换。
<input v-model="message">
// ...
computed: {
message: {
get () {
return this.$store.state.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
复制代码