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)
}
}
}
複製代碼