您好,登錄后才能下訂單哦!
在用vue作為前端框架進(jìn)行開發(fā)的時(shí)候,對(duì)于組件間的傳值你一定不會(huì)陌生,如果只是簡(jiǎn)單的父子組件傳值,我想你肯定不會(huì)選擇用Vuex來進(jìn)行狀態(tài)管理,但是如果你需要構(gòu)建一個(gè)中大型單頁應(yīng)用,組件間數(shù)據(jù)交互比較復(fù)雜頻繁,你很可能會(huì)考慮如何更好地在組件外部管理狀態(tài),那么Vuex 將會(huì)成為自然而然的選擇。
Vuex 是什么?
Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。 這是官方的一種說法。
用個(gè)人的話總結(jié)下: Vuex就是為了實(shí)現(xiàn)多組件數(shù)據(jù)共享,從而建立一個(gè)叫store的數(shù)據(jù)管理庫,將需要共享的數(shù)據(jù)存放在里面,在需要的地方可以取出來作為初始數(shù)據(jù),也可以在組件內(nèi)通過dispatch或者提交commit方法來改變?cè)撛紨?shù)據(jù)狀態(tài),從而實(shí)現(xiàn)的data的共享。
Vuex的核心
1、 State
Vuex中的數(shù)據(jù)源,我們需要保存的數(shù)據(jù)就保存在這里,可以在頁面通過this.$store.state
來獲取我們定義的數(shù)據(jù)。
import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); const state = { number: 0 } export default new Vuex.Store({ state, });
在頁面中通過this.$store.state.number
即可獲取到當(dāng)前的值。
2、Getter
Vuex 允許我們?cè)?store 中定義“getter”(可以認(rèn)為是 store 的計(jì)算屬性)。就像計(jì)算屬性一樣,getter 的返回值會(huì)根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生了改變才會(huì)被重新計(jì)算。
Getter 接受 state 作為其第一個(gè)參數(shù):
import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); const state = { number: 0 } const getters = { getNumber(state) { return state.number + 1 } } export default new Vuex.Store({ state, getters, });
在頁面你可以用兩種方式取到getters里面的值
1、通過屬性訪問
Getter 會(huì)暴露為 store.getters 對(duì)象,你可以以屬性的形式訪問這些值 如: this.$store.getters.getNumber
Getter 也可以接受其他 getter 作為第二個(gè)參數(shù):
const state = { number: 1 } const getters = { getNumber(state) { return state.number + 1 // 2 }, getDoubNUmber(state, getters) { return state.number + getters.getNumber // 3 } }
注意: getter 在通過屬性訪問時(shí)是作為 Vue 的響應(yīng)式系統(tǒng)的一部分緩存其中的。
2、 通過方法訪問
你也可以通過讓 getter 返回一個(gè)函數(shù),來實(shí)現(xiàn)給 getter 傳參。在你對(duì) store 里的數(shù)組進(jìn)行查詢時(shí)非常有用。
const state = { number: 1, list: [1, 2, 3, 4, 5] } const getters = { getNumber(state) { return state.number + 1 // 2 }, getDoubNumber(state, getters) { return state.number + getters.getNumber // 3 }, filterNumber:(state)=>(num)=> { return state.list.find(item=> item%num === 0) } } export default new Vuex.Store({ state, getters, });
注意, getter 在通過方法訪問時(shí),每次都會(huì)去進(jìn)行調(diào)用,而不會(huì)緩存結(jié)果 this.$store.getters.filterNumber(3)
3、Mutation
更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方, 并且它會(huì)接受 state 作為第一個(gè)參數(shù) , 提交載荷(payload) 作為額外的參數(shù) ,并且在大多數(shù)情況下,載荷應(yīng)該是一個(gè)對(duì)象,這樣可以包含多個(gè)字段并且使記錄的 mutation 會(huì)更易讀:
你可以這樣寫:
const mutations = { increment(state, n) { state.number += n } }
但你不能直接調(diào)用一個(gè) mutation handler。這個(gè)選項(xiàng)更像是事件注冊(cè):“當(dāng)觸發(fā)一個(gè)類型為 increment 的 mutation 時(shí),調(diào)用此函數(shù)?!币獑拘岩粋€(gè) mutation handler,你需要以相應(yīng)的 type 調(diào)用 store.commit 方法:
this.$store.commit('increment', 1)
也可以這樣寫:
const mutations = { increment(state, payload) { state.number += payload.count } }
然后:
使用 this.$store.commit('increment', {count: 1})
提交,
// 或者另一種方式是直接使用包含 type 屬性的對(duì)象進(jìn)行提交: this.$store.commit({ type: 'increment', count: 1 })
特別說明:在 Vuex 中,mutation 都是同步任務(wù):為了處理異步操作,讓我們來看一看 Action。
4、 Action
Action 類似于 mutation,不同在于:
1、Action 提交的是 mutation,而不是直接變更狀態(tài)。
2、Action 可以包含任意異步操作。
雖然在頁面中通過提交commit是可以達(dá)到修改store中狀態(tài)值的目的,但是官方并不建議我們這樣做,而是讓我們?nèi)ヌ峤灰粋€(gè)action,在action中提交mutation再去修改狀態(tài)值。
const mutations = { increment(state) { state.number += 1 } } const actions = { addNumber(context){ context.commit('increment') } }
Action 函數(shù)接受一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象,因此你可以調(diào)用 context.commit 提交一個(gè) mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters
addNumber( {commit} ){ commit('increment') }
以上這種寫法等同于:
addNumber(context){ context.commit('increment') }
Action 通過 store.dispatch 方法觸發(fā):
this.$store.dispatch('addNumber')
同mutation 一樣你也可以在action的時(shí)候傳遞參數(shù)
const mutations = { increment(state, number) { state.number += number } } const actions = { addNumber(context, number){ context.commit('increment', number) } 或者: addNumber( {commit}, number){ commit('increment', number) } }
觸發(fā)方法: this.$store.dispatch('addNumber', 10)
關(guān)于在action 處理異步操作可以看下面這個(gè)例子:
const actions = { getData({commit}) { return new Promise((resolve, reject)=> { setTimeout(()=>{ commit('getList') resolve() }, 1000) }) } }
然后再
this.$store.dispatch('getData').then(() => { // ... })
完整 實(shí)例:
import Vue from "vue"; import Vuex from "vuex"; import { resolve, reject } from "any-promise"; Vue.use(Vuex); const state = { number: 1, list: [1, 2, 3, 4, 5] } const getters = { getNumber(state) { return state.number + 1 // 2 }, getDoubNumber(state, getters) { return state.number + getters.getNumber // 3 }, filterNumber:(state)=>(num)=> { return state.list.find(item=> item%num === 0) } } const mutations = { increment(state, n) { state.number += n }, getList(state) { state.list = state.list.forEach((item)=> item*2) } } const actions = { addNumber( {commit} , n){ commit('increment', n) }, getData({commit}) { return new Promise((resolve, reject)=> { setTimeout(()=>{ commit('getList') resolve() }, 1000) }) } } export default new Vuex.Store({ state, getters, mutations, actions });
關(guān)于 Vuex中mapState、mapGetters、mapMutations、mapActions的用法
要用 首先得引入:
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
這玩意兒其實(shí)就是Vuex 內(nèi)置的輔助函數(shù),方便我們獲取store里面的數(shù)據(jù)和方法
computed: { ...mapState([ 'number' ]) } // 使用對(duì)象展開運(yùn)算符將 getter 混入 computed 對(duì)象中 computed: { ...mapGetters([ 'getNumber', 'getDoubNumber', // ... ]) } methods: { ...mapMutations([ 'increment', // 將 `this.increment()` 映射為 `this.$store.commit('increment')` ...mapMutations({ add: 'increment' // 將 `this.add()` 映射為 `this.$store.commit('increment')` }) } methods: { ...mapActions([ 'addNumber', // 將 `this.addNumber()` 映射為 `this.$store.dispatch('addNumber')` // `mapActions` 也支持載荷: 'addNumber' // 將 `this.addNumber(amount)` 映射為 `this.$store.dispatch('addNumber', amount)` ]), ...mapActions({ requestData: 'getData' // 將 `this.requestData()` 映射為 `this.$store.dispatch('getData')` }) }
以上是對(duì)Vuex實(shí)現(xiàn)狀態(tài)管理的一個(gè)整個(gè)過程的理解,參考官方文檔,然后自己寫一遍,比較容易明白其中的道理,后面有時(shí)間想寫React里面關(guān)于Redux實(shí)現(xiàn)狀態(tài)管理的一個(gè)過程,對(duì)比其中,其實(shí)他們思想差不多, 只不過redux實(shí)現(xiàn)過程更多點(diǎn),敬請(qǐng)期待!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。