Vuex 通俗版教程

本文基本上是官方教程的盜版,用通俗易懂的文字講解Vuex,也對(duì)原文內(nèi)容有刪減。

如果你對(duì)以上聲明不介意,那么就可以繼續(xù)看本文,希望對(duì)你有所幫助。

學(xué)習(xí)一個(gè)新技術(shù),必須要清楚兩個(gè)W,"What && Why"。

"XX 是什么?","為什么要使用 XX ,或者說(shuō) XX 有什么好處",最后才是"XX 怎么使用"。

Vuex是什么?

Vuex 類似 Redux 的狀態(tài)管理器,用來(lái)管理Vue的所有組件狀態(tài)。

為什么使用Vuex?

當(dāng)你打算開發(fā)大型單頁(yè)應(yīng)用(SPA),會(huì)出現(xiàn)多個(gè)視圖組件依賴同一個(gè)狀態(tài),來(lái)自不同視圖的行為需要變更同一個(gè)狀態(tài)。

遇到以上情況時(shí)候,你就應(yīng)該考慮使用Vuex了,它能把組件的共享狀態(tài)抽取出來(lái),當(dāng)做一個(gè)全局單例模式進(jìn)行管理。這樣不管你在何處改變狀態(tài),都會(huì)通知使用該狀態(tài)的組件做出相應(yīng)修改。

下面講解如何使用Vuex。

最簡(jiǎn)單的Vuex示例

本文就不涉及如何安裝Vuex,直接通過(guò)代碼講解。

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        count: 0
    },
    mutations: {
        increment (state) {
            state.count++
        }
    }
})

以上就是一個(gè)最簡(jiǎn)單的Vuex,每一個(gè)Vuex應(yīng)用就是一個(gè)store,在store中包含組件中的共享狀態(tài)state和改變狀態(tài)的方法(暫且稱作方法)mutations。

需要注意的是只能通過(guò)mutations改變store的state的狀態(tài),不能通過(guò)store.state.count = 5;直接更改(其實(shí)可以更改,不建議這么做,不通過(guò)mutations改變state,狀態(tài)不會(huì)被同步)。

使用store.commit方法觸發(fā)mutations改變state:

store.commit('increment');

console.log(store.state.count)  // 1

一個(gè)簡(jiǎn)簡(jiǎn)單單的Vuex應(yīng)用就實(shí)現(xiàn)了。

在Vue組件使用Vuex

如果希望Vuex狀態(tài)更新,相應(yīng)的Vue組件也得到更新,最簡(jiǎn)單的方法就是在Vue的computed(計(jì)算屬性)獲取state

// Counter 組件
const Counter = {
    template: `<div>{{ count }}</div>`,
    computed: {
        count () {
            return store.state.count;
        }
    }
}

上面的例子是直接操作全局狀態(tài)store.state.count,那么每個(gè)使用該Vuex的組件都要引入。為了解決這個(gè),Vuex通過(guò)store選項(xiàng),提供了一種機(jī)制將狀態(tài)從根組件注入到每一個(gè)子組件中。

// 根組件
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);
const app = new Vue({
    el: '#app',
    store,
    components: {
        Counter
    },
    template: `
        <div class="app">
            <counter></counter>
        </div>
    `
})

通過(guò)這種注入機(jī)制,就能在子組件Counter通過(guò)this.$store訪問(wèn):

// Counter 組件
const Counter = {
    template: `<div>{{ count }}</div>`,
    computed: {
        count () {
            return this.$store.state.count
        }
    }
}

mapState函數(shù)

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

這樣通過(guò)count計(jì)算屬性獲取同名state.count屬性,是不是顯得太重復(fù)了,我們可以使用mapState函數(shù)簡(jiǎn)化這個(gè)過(guò)程。

import { mapState } from 'vuex';

export default {
    computed: mapState ({
        count: state => state.count,
        countAlias: 'count',    // 別名 `count` 等價(jià)于 state => state.count
    })
}

還有更簡(jiǎn)單的使用方法:

computed: mapState([
  // 映射 this.count 為 store.state.count
  'count'
])

Getters對(duì)象

如果我們需要對(duì)state對(duì)象進(jìn)行做處理計(jì)算,如下:

computed: {
    doneTodosCount () {
        return this.$store.state.todos.filter(todo => todo.done).length
    }
}

如果多個(gè)組件都要進(jìn)行這樣的處理,那么就要在多個(gè)組件中復(fù)制該函數(shù)。這樣是很沒(méi)有效率的事情,當(dāng)這個(gè)處理過(guò)程更改了,還有在多個(gè)組件中進(jìn)行同樣的更改,這就更加不易于維護(hù)。

Vuex中getters對(duì)象,可以方便我們?cè)?code>store中做集中的處理。Getters接受state作為第一個(gè)參數(shù):

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

在Vue中通過(guò)store.getters對(duì)象調(diào)用。

computed: {
  doneTodos () {
    return this.$store.getters.doneTodos
  }
}

Getter也可以接受其他getters作為第二個(gè)參數(shù):

getters: {
  doneTodos: state => {
      return state.todos.filter(todo => todo.done)
  },
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}

mapGetters輔助函數(shù)

mapState類似,都能達(dá)到簡(jiǎn)化代碼的效果。mapGetters輔助函數(shù)僅僅是將store中的getters映射到局部計(jì)算屬性:

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
    // 使用對(duì)象展開運(yùn)算符將 getters 混入 computed 對(duì)象中
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}

上面也可以寫作:

computed: mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])

所以在Vue的computed計(jì)算屬性中會(huì)存在兩種輔助函數(shù):

import { mapState, mapGetters } from 'vuex';

export default {
    // ...
    computed: {
        mapState({ ... }),
        mapGetter({ ... })
    }
}

Mutations

之前也說(shuō)過(guò)了,更改Vuex的store中的狀態(tài)的唯一方法就是mutations。

每一個(gè)mutation都有一個(gè)事件類型type和一個(gè)回調(diào)函數(shù)handler。

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 變更狀態(tài)
      state.count++
    }
  }
})

調(diào)用mutation,需要通過(guò)store.commit方法調(diào)用mutation type

store.commit('increment')

Payload 提交載荷

也可以向store.commit傳入第二參數(shù),也就是mutation的payload:

mutaion: {
    increment (state, n) {
        state.count += n;
    }
}

store.commit('increment', 10);

單單傳入一個(gè)n,可能并不能滿足我們的業(yè)務(wù)需要,這時(shí)候我們可以選擇傳入一個(gè)payload對(duì)象:

mutation: {
    increment (state, payload) {
        state.totalPrice += payload.price + payload.count;
    }
}

store.commit({
    type: 'increment',
    price: 10,
    count: 8
})

mapMutations函數(shù)

不例外,mutations也有映射函數(shù)mapMutations,幫助我們簡(jiǎn)化代碼,使用mapMutations輔助函數(shù)將組件中的methods映射為store.commit調(diào)用。

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment' // 映射 this.increment() 為 this.$store.commit('increment')
    ]),
    ...mapMutations({
      add: 'increment' // 映射 this.add() 為 this.$store.commit('increment')
    })
  }
}

Mutations必須是同步函數(shù)。

如果我們需要異步操作,Mutations就不能滿足我們需求了,這時(shí)候我們就需要Actions了。

Aciton

相信看完之前的Vuex的內(nèi)容,你就已經(jīng)入門了。那么Action就自己進(jìn)行學(xué)習(xí)吧(Action有點(diǎn)復(fù)雜,我還需要時(shí)間消化)。

結(jié)語(yǔ)

上個(gè)月看Vuex還是一頭霧水,現(xiàn)在看來(lái)Vuex也是很容易理解的。

學(xué)習(xí)一門新技術(shù)最重要的就是實(shí)踐,單單看教程和demo是遠(yuǎn)遠(yuǎn)不夠的。

前端路途漫漫,共勉。

個(gè)人博客:https://yeaseonzhang.github.io

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(V...
    F_imok閱讀 2,690評(píng)論 0 12
  • 寫在文前: 最近一直在用vue開發(fā)項(xiàng)目,寫來(lái)寫去就是那么些方法,對(duì)于簡(jiǎn)單的項(xiàng)目一些常用的vue方法足以解決,但是涉...
    _littleTank_閱讀 22,632評(píng)論 5 38
  • 安裝 npm npm install vuex --save 在一個(gè)模塊化的打包系統(tǒng)中,您必須顯式地通過(guò)Vue.u...
    蕭玄辭閱讀 3,035評(píng)論 0 7
  • Vuex是什么? Vuex 是一個(gè)專為 Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件...
    蕭玄辭閱讀 3,230評(píng)論 0 6
  • vuex 場(chǎng)景重現(xiàn):一個(gè)用戶在注冊(cè)頁(yè)面注冊(cè)了手機(jī)號(hào)碼,跳轉(zhuǎn)到登錄頁(yè)面也想拿到這個(gè)手機(jī)號(hào)碼,你可以通過(guò)vue的組件化...
    sunny519111閱讀 8,156評(píng)論 4 111

友情鏈接更多精彩內(nèi)容