Vuex 是 Vue.js 的官方狀態管理工具。在這篇教程中,我將解釋它的基本用法。

簡介到 Vuex

Vuex 是 Vue.js 的官方狀態管理工具。

它的工作是在應用程式的組件之間共享數據。

在 Vue.js 中,組件可以使用以下方式進行通訊:

  • props,從父組件將狀態傳遞給子組件。
  • events,從子組件更改父組件的狀態,或將根組件用作事件匯流排。

有時候,這些簡單的方法可能無法滿足需求。

在這種情況下,最好的選擇是將狀態集中存儲在一個單獨的 store 中。這就是 Vuex 的作用。

為什麼應該使用 Vuex

在 Vue 中,你可以使用 Vuex 之外的其他狀態管理工具(例如 Redux),但 Vuex 的主要優勢在於它是官方推薦的,並且與 Vue.js 的整合非常出色。

與 React 不同,你需要從眾多的庫中選擇一個,因為 React 生態系統龐大,並沒有一個明確的標準。最近,Redux 是最受歡迎的選擇,其次是 MobX。而在 Vue 中,我敢肯定說,你不需要尋找其他選擇,Vuex 就是最好的選擇,特別是當你剛開始時。

Vuex 借鑒了 React 生態系統的許多思想,因為它們都遵循了 Redux 引入的 Flux 模式。

如果你已經熟悉 Flux 或 Redux,那麼 Vuex 將非常容易理解。如果你不熟悉,沒有問題-我將從頭開始解釋每個概念。

Vue 應用程式中的組件可以擁有自己的狀態。例如,輸入框將在本地存儲輸入的數據。這是完全可以的,即使使用了 Vuex,組件也可以擁有本地狀態。

當你開始使用各種方法傳遞狀態時,就知道你需要像 Vuex 這樣的東西了。

在這種情況下,Vuex 提供了一個集中存儲狀態的存儲庫,並且通過要求存儲庫來改變狀態。

每個依賴於特定狀態的組件都可以使用存取器從存儲庫中獲取狀態,這將確保在該狀態發生變化時立即更新。

使用 Vuex 將使應用程式變得更為複雜,因為需要按照一定的方式設定才能正確工作,但如果能解決繁瑣的道路傳遞和事件系統所帶來的混亂,它是一個不錯的選擇。

讓我們開始吧

在這個例子中,我將從 Vue CLI 應用程式開始。Vuex 也可以通過直接將其載入到 script 標籤中來使用,但由於 Vuex 更適合於大型應用程式,所以您更有可能在結構化的應用程式中使用它,例如使用 Vue CLI 快速啟動的應用程式。

我使用的示例代碼將放在 CodeSandbox 上,CodeSandbox 是一個很棒的服務,已經準備好了一個 Vue CLI 的示例,您可以在 https://codesandbox.io/s/vue 上使用它。我建議您使用它來進行實驗。

CodeSandbox

進入 CodeSandbox 後,點擊Add dependency按鈕,輸入 “vuex” 並單擊它。

現在 Vuex 將在項目的依賴項中列出。

要在本地安裝 Vuex,您可以在項目文件夾中運行 npm install vuexyarn add vuex

建立 Vuex store

現在我們已經準備好創建 Vuex store。

這個文件可以放在任何地方。通常建議將它放在 src/store/store.js 文件中,因此我們將這樣做。

在這個文件中,我們初始化 Vuex,並告訴 Vue 使用它:

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

Vue.use(Vuex)

export const store = new Vuex.Store({})

我們導出了一個 Vuex store 對象,該對象使用 Vuex.Store() API 創建。

一個使用 store 的使用案例

現在我們有了基礎,讓我們想一個對於 Vuex 的使用案例,以便我能夠介紹它的概念。

例如,我有兩個兄弟組件,一個包含一個輸入框,另一個打印該輸入框的內容。

當輸入框改變時,我希望也更改第二個組件中的內容。非常簡單,但對於我們來說勢必適合。

介紹我們需要的新組件

我刪除 HelloWorld 組件,添加一個 Form 組件和一個 Display 組件。

<template>
 <div>
 <label for="flavor">Favorite ice cream flavor?</label>
 <input name="flavor">
 </div>
</template>
<template>
 <div>
 <p>You chose ???</p>
 </div>
</template>

將這些組件添加到應用程式中

我們將它們添加到 App.vue 代碼中,而不是添加到 HelloWorld 組件中:

<template>
 <div id="app">
 <Form/>
 <Display/>
 </div>
</template>

<script>
import Form from './components/Form'
import Display from './components/Display'

export default {
 name: 'App',
 components: {
 Form,
 Display
 }
}
</script>

將狀態添加到 store 中

在這個基礎上,我們回到 store.js 文件,並在 store 中添加一個名為 state 的屬性,它是一個包含 flavor 屬性的對象。初始值為空字符串。

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

Vue.use(Vuex)

export const store = new Vuex.Store({
 state: {
 flavor: ''
 }
})

當用戶在輸入框中輸入時,我們將更新它。

添加一個 Mutation

狀態可以使用 mutations 進行更改。我們設置了一個 mutation,在 Form 組件中使用它來通知 store 狀態應該更改。

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

Vue.use(Vuex)

export const store = new Vuex.Store({
 state: {
 flavor: ''
 },
 mutations: {
 change(state, flavor) {
 state.flavor = flavor
 }
 }
})

添加一個 getter 來引用狀態屬性

設置完成後,我們需要一種方式來查看狀態。我們使用 getters 來實現這一目的。我們為 flavor 屬性設置了一個 getter:

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

Vue.use(Vuex)

export const store = new Vuex.Store({
 state: {
 flavor: ''
 },
 mutations: {
 change(state, flavor) {
 state.flavor = flavor
 }
 },
 getters: {
 flavor: state => state.flavor
 }
})

請注意,getters 是一個對象,flavor 是此對象的一個屬性,它接受狀態作為參數,並返回狀態的 flavor 屬性。

將 Vuex store 添加到應用程式中

現在可以使用 store 了。回到我們的應用程式代碼中,在 main.js 文件中,我們需要導入狀態並使其在 Vue 應用程式中可用。

我們導入

import { store } from './store/store'

並將其添加到 Vue 應用程式中:

new Vue({
 el: '#app',
 store,
 components: { App },
 template: '<App/>'
})

一旦添加這個,由於這是主要的 Vue 組件,每個 Vue 組件中的 store 變量都將指向 Vuex store。

使用 commit 在使用者操作中更新狀態

讓我們在用戶輸入時更新狀態。

我們使用 store.commit() API 實現這一目的。

但首先,讓我們創建一個方法,當輸入內容改變時調用該方法。我們使用 @input 而不是 @change,因為後者只在焦點從輸入框移開時觸發,而 @input 在每個按鍵按下時都會調用。

<template>
 <div>
 <label for="flavor">Favorite ice cream flavor?</label>
 <input @input="changed" name="flavor">
 </div>
</template>

<script>
export default {
 methods: {
 changed: function(event) {
 alert(event.target.value)
 }
 }
}
</script>

現在我們有了 flavor 的值,我們使用 Vuex API:

<script>
export default {
 methods: {
 changed: function(event) {
 this.$store.commit('change', event.target.value)
 }
 }
}
</script>

看到我們如何使用 this.$store 引用 store 嗎?這是由於在主 Vue 組件初始化中包含了 store 對象。

commit() 方法接受一個 mutation 名稱(我們在 Vuex store 中使用了 change),以及一個作為回調函數的第二個參數的載荷,將傳遞給該 mutation 作為第二個參數。

使用 getter 來打印狀態值

現在,我們需要在 Display 模板中引用此值的 getter,使用 $store.getters.flavor。可以移除 this,因為我們在模板中,而 this 是隱式的。

<template>
 <div>
 <p>You chose {{ $store.getters.flavor }}</p>
 </div>
</template>

總結

這就是關於 Vuex 的介紹了!

完整可運行的代碼可以在 https://codesandbox.io/s/zq7k7nkzkm 找到。

這裡還有很多概念需要學習:

  • actions
  • modules
  • helpers
  • plugins

但你已經掌握了基本知識,可以在官方文檔中了解更多相關資訊。

祝你編碼愉快!