Vuex入門


vue 開發中,組件通信一直是一大痛點。

當項目是很簡單的 SPA 或者多入口項目時,可以靠着 vue 自帶的 prop/$emit 進行組件通信;規模再大一些,可以搭配使用 bus 總線進行兄弟組件通信;項目再大一些,出現更復雜的組件關系時,復雜的組件通信可以讓你寫得懷疑人生。

萬幸的是, vue 官方出品了 vuex ,通過全局式的狀態管理,解決了這一痛點。

雖然 vuex 很好用,但是,很多小伙伴和我吐槽 vuex 的文檔和 vue-ssr 的文檔一樣,讓人看得一臉懵逼。

好吧,下面就讓我來帶着大家一起入門 vuex

安裝並引入

正常情況下,我們使用 vue-cli3 生成項目時,可以選擇集成 vuex 到項目中。此時, vue-cli3 會自動安裝 vuex ,並在 src 文件夾下生成 store.js 完成 vuex 的引入和配置。

但是,很多同學並沒有使用 vue-cli3 或者生成項目時沒有選擇集成 vuex 。此時,就只能手動安裝並引入 vuex 了。

安裝

由於 vuex 是用於全局狀態管理的,所以,它不僅僅作用於開發環境,而且還要用於生產環境。

顯而易見,安裝 vuex 應該使用 -S--save 命令。

npm install vuex -S

引入

類似於 vue-cli3 生成的項目,我們在 src 文件夾下新建 store.js ,並在其中寫入:

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({})

然后,我們只需要在 vue 實例中引入 store.js 中的 Vuex.Store 實例即可:

// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  // 引入store
  store,
  render: h => h(App)
}).$mount('#app')

Vuex的使用

完成了 vuex 的安裝和引入,接下來我們進入 Vuex 的使用。

vuex 中有三要素: statemutation 以及 action 。它們之間的關系可以用官網那張著名的圖來表示:

vuex

State

簡單來說, state 表示狀態,類似於 vue 中的 data (其實本質上就是差不多的, vuexvuebeforeCreate 鈎子中將 state 混入進 data)。但是,它們又有很大的不同: 在使用者看來, state 是全局的,這得益於 vuex 的設計理念——單一狀態樹。這些我將在后幾篇文章中詳細,現在我們只需要知道 state 是類似於全局下的 data

接下來我們通過一個簡單例子來感受下 state

首先,我們需要修改 store.js 文件,配置 state 。可以看到,我們在生成 Vuex.Store 實例時傳入了實例化選項對象,對象包含一個 state 屬性, state 對象的屬性就是我們定義的全局狀態。

此時,我們定義了一個全局狀態——count ,並將其的初始值設為1

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  // 添加state
  state: {
    count: 1
  }
})

接下來,我們需要在組件中引用 count,由於它是全局狀態,我們可以在任何一個組件中使用。為了展示其威力,我們在兩個不同的組件中使用它。

首先我們在 App.vue 中使用它:

在模板中,我們使用 $store.state.count 引入該全局狀態,沒錯,使用它就是那么簡單,只需要 以 $store.state.key 的形式調用。

// App.vue
<template>
  <div id="app">
    <div id="nav">
      {{$store.state.count}}
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>

可以發現, Home 前多出了一個 1 ,這代表着我們成功引入了全局狀態 count

接下來我們在 Home.vue 的子組件 HelloWorld.vue 中引入 count

相同的引用方式: $store.state.count

// HelloWorld.vue
<template>
  <div class="hello">
    {{$store.state.count}}
  </div>
</template>

可以發現,頁面中又多出了一個 1 ,代表着我們又一次引用成功。現在,是不是已經感受到了 vuex 的威力?

Mutation

但是,上面的示例有個問題,那就是全局狀態是靜態的。如果在實際應用場景中,一般來說,會經常更改狀態。

有的同學會說,我們直接在方法中修改 this.$store.state.key 的值不就行了嗎?

不好意思,當然是不行的。

statedata 的另一大區別在於,你不能直接改變 state 。改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化,從而讓我們能夠實現一些工具幫助我們更好地了解我們的應用。

簡而言之,我們把 mutation 當做接收 state 作為參數並修改 state 的自定義事件即可,上一段所說的 commit 就是觸發 mutaion 這個自定義事件的方法。

光說不練假把式,接下來,我們對為 vuex 添加上 mutation ,實現 state 的動態改變:

首先,當然是修改生成 Vuex.Store 示例的選項對象,為其添加 mutations

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1
  },
  // 添加mutation
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

在上面的代碼中,我們添加了一個名為 incrementmutation 。完成了自定義事件,接下來,我們只需要在組件中對 mutation 進行觸發即可。

我們在 HelloWorld.vue 添加一個按鈕,每次點擊觸發一次 increment 這個 mutation 。可以發現,觸發方式很簡單,只需要調用 store 自帶的 commit 方法,其中參數為需要觸發的 mutation 的名稱。

// HelloWorld.vue
<template>
  <div class="hello">
    <div>{{$store.state.count}}</div>
    <button @click="$store.commit('increment')">修改count</button>
  </div>
</template>

點擊頁面中的按鈕,你會發現,頁面中的兩個 count 都同時增加了1,說明我們成功實現了 state 的動態修改。

Action

action 類似於 mutation ,也相當於一種自定義事件。只不過, action 操作的是 mutation 而不是 state

添加 action 的方法類似,在選項對象中新增 action 屬性即可。與 mutation 的參數不同, action 的參數就是當前創建的 Vue.store 對象實例的上下文,一般將其命名為 context 。我們需要使用其自帶的 commit 方法來觸發 mutation

下面我通過實際的例子來嘗試下 action

首先,修改選項對象,使得新添加的 action 可以觸發之前的 mutation

// store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment ({ commit }) {
      commit('increment')
    }
  }
})

由於我們一般來說僅僅需要 context 中的 commit 方法,所以可以采用解構的方式,直接調用 commit 方法,而不需要以 context.commit 的方式使用它。

接下來,只需要修改 HelloWorld.vue ,使其能夠在點擊按鈕時觸發即可。

action 的觸發方式和 mutation 類似,只不過調用的方法是 dispatch

// HelloWorld.vue
<template>
  <div class="hello">
    <div>{{$store.state.count}}</div>
    <button @click="$store.dispatch('increment')">修改count</button>
  </div>
</template>

點擊頁面按鈕,你會發現,實現了和之前相同的效果。

總結

學會了 vuex 三賤客: statemutationaction ,我們再回過頭看看前面的那張關系圖,此時應該很容易理解了吧?

組件交互觸發 action , 在 action 中進行異步操作(可選)並觸發 mutationmutation 控制 state 的變動, state 修改之后,觸發響應式,重新渲染組件。

彩蛋

在官方文檔中,提到需要將異步操作放入 action 中,而不能放在 mutation 中。實際上,在 mutation 中也可以進行異步操作,而且也不會導致什么奇怪的事情。

但是,既然官方文檔中這么說了,我們在實際開發中,一般還是老老實實地將所有異步操作放在 action 中。(猥瑣保平安 -_-)

另外,說了這么多,其實在一些項目中,可以使用 provide/inject 代替 vuex 。具體的用法在此不再贅述,就當一個課后作業吧。

在項目中靈活使用 provide/inject ,有時可以起到出乎意料的作用哦。

最后的最后

篇幅有限,所以該篇文章只講述了 vuex 三賤客的基本用法,其他的進階用法,如: gettermodule , 簡寫以及 vuex 項目結構優化,甚至 vuex 源碼解析將會在之后的文章一一講解。

如果您覺得這片文章不錯的話,不如給我的 gayhub 點個star再走唄。

這個項目個人認為對很多新手在實際開發中使用 vuex 還是很有啟發和幫助的(手動狗頭)。

歡迎交流,謝謝~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM