十分鐘讓你了解vuex原理和入門知識

2021-05-2919:29:42十分鐘讓你了解vuex原理和入門知識已關閉評論
摘要

Vuex 是Vue.js 應用程序的狀態管理模式 + 庫。它充當應用程序中所有組件的集中存儲,其規則確保狀態只能以可預測的方式改變。它還與 Vue 的官方devtools 擴展集成?(打開新窗口)提供高級功能,例如零配置時間旅行調試和狀態快照導出/導入。

 

Vuex 簡介

Vuex 是Vue.js 應用程序的狀態管理模式 + 庫。它充當應用程序中所有組件的集中存儲,其規則確保狀態只能以可預測的方式改變。它還與 Vue 的官方devtools 擴展集成?(打開新窗口)提供高級功能,例如零配置時間旅行調試和狀態快照導出/導入。

vuex原理

讓我們從一個簡單的 Vue 計數器應用程序開始:

new Vue({
  // state
  data () {
    return {
      count: 0
    }
  },
  // view
  template: `
    <div>{{ count }}</div>
  `,
  // actions
  methods: {
    increment () {
      this.count++
    }
  }
})

它是一個獨立的應用程序,包含以下部分:

  • 狀態,真理,推動我們的應用程序的來源;
  • 視圖,所述的聲明性映射狀態;
  • 動作,可能的方式的狀態可以從反應于用戶輸入改變視圖

這是“單向數據流”概念的簡單表示:

然而,當我們有多個共享一個公共狀態的組件時,這種簡單性很快就會崩潰:

  • 多個視圖可能依賴于同一個狀態。
  • 來自不同視圖的操作可能需要改變相同的狀態。

對于問題一,傳遞 props 對于深度嵌套的組件可能很乏味,而且對于兄弟組件根本不起作用。對于問題二,我們經常發現自己求助于解決方案,例如獲取直接的父/子實例引用或嘗試通過事件來改變和同步多個狀態副本。這兩種模式都很脆弱,很快就會導致無法維護的代碼。

那么為什么我們不從組件中提取共享狀態,并在全局單例中管理它呢?這樣,我們的組件樹就變成了一個大“視圖”,任何組件都可以訪問狀態或觸發動作,無論它們在樹中的哪個位置!

通過定義和分離狀態管理中涉及的概念并強制執行維護視圖和狀態之間獨立性的規則,我們為我們的代碼提供了更多的結構和可維護性。

這是 Vuex 背后的基本思想,受Flux啟發??與其他模式不同,Vuex 也是一個專門為 Vue.js 量身定制的庫實現,以利用其粒度反應系統進行高效更新。

如果你想以交互方式學習 Vuex,你可以在 Scrimba 上查看這個Vuex 課程?(打開新窗口),它為您提供了截屏視頻和代碼游樂場的組合,您可以隨時暫停和播放。

Vuex

#我應該什么時候使用它?

Vuex 幫助我們以更多的概念和樣板為代價來處理共享狀態管理。這是短期和長期生產力之間的權衡。

如果您從未構建過大型 SPA 并直接跳入 Vuex,那可能會感到冗長和令人生畏。這是完全正常的 - 如果您的應用程序很簡單,那么您很可能沒有 Vuex 也可以。一個簡單的存儲模式?(打開新窗口)可能就是你所需要的。但是,如果您正在構建一個中大型 SPA,您可能會遇到一些情況,讓您考慮如何更好地處理 Vue 組件之外的狀態,而 Vuex 將是您的下一步。Redux的作者Dan Abramov有一個很好的報價:

Flux 庫就像眼鏡:你會知道什么時候需要它們。

Vuex 是 Vue.js 的官方狀態管理庫。它的工作是在應用程序的組件之間共享數據。開箱即用的 Vue.js 中的組件可以使用

  • props,將狀態從父組件傳遞給子組件
  • events,從子組件更改父組件的狀態,或使用根組件作為事件總線

有時事情會變得比這些簡單選項所允許的更復雜。

在這種情況下,一個不錯的選擇是將狀態集中在一個商店中。這就是 Vuex 所做的。

為什么要使用 Vuex

Vuex 不是您可以在 Vue 中使用的唯一狀態管理選項(您也可以使用Redux),但它的主要優點是它是官方的,并且它與 Vue.js 的集成使它發光。

使用React,您將不得不選擇眾多可用庫中的一種,因為該生態系統龐大且沒有實際標準。最近 Redux 是最受歡迎的選擇,MobX 在流行度方面緊隨其后。使用 Vue,我什至要說除了 Vuex 之外,您不需要四處尋找任何東西,尤其是在開始時。

Vuex 借鑒了 React 生態系統的許多想法,因為這是 Redux 推廣的 Flux 模式。

如果您已經了解 Flux 或 Redux,那么 Vuex 會非常熟悉。如果你不這樣做,沒問題 - 我會從頭開始解釋每個概念。

Vue 應用程序中的組件可以有自己的狀態。例如,輸入框會將輸入的數據存儲在本地。這非常好,即使使用 Vuex,組件也可以具有本地狀態。

你知道當你開始做大量工作來傳遞一個狀態時,你需要像 Vuex 這樣的東西。

在這種情況下,Vuex 為狀態提供了一個中央存儲庫,您可以通過要求存儲來改變狀態。

每個依賴于特定狀態部分的組件都將使用 store 上的 getter 訪問它,這確保它在事情發生變化時立即更新。

使用 Vuex 會給應用程序帶來一些復雜性,因為需要以某種方式設置才能正常工作,但是如果這有助于解決無組織的 props 傳遞和事件系統,如果過于復雜,可能會變成意大利面條式的混亂,那么它就是一個不錯的選擇。

開始吧

在這個例子中,我從一個Vue CLI應用程序開始。Vuex 也可以通過直接將其加載到腳本標簽中來使用,但由于 Vuex 更適合更大的應用程序,因此您更有可能將它用于更結構化的應用程序,例如您可以使用 Vue 快速啟動的應用程序命令行界面。

我使用的示例將放在 CodeSandbox,這是一個很棒的服務,它有一個 Vue CLI 示例,可以在https://codesandbox.io/s/vue 上使用。我建議用它來玩。

代碼沙盒

到達那里后,單擊“添加依賴項”按鈕,輸入“vuex”并單擊它。

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

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

創建 Vuex 商店

現在,我們準備創建Vuex商店。

這個文件可以放在任何地方。一般建議把它放在src/store/store.js文件中,所以我們會這樣做。

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

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

Vue.use(Vuex)

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

Vuex 商店

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

商店的用例

現在我們有了一個框架,讓我們為 Vuex 的一個好的用例提出一個想法,這樣我就可以介紹它的概念。

例如,我有 2 個同級組件,一個帶有輸入字段,另一個打印輸入字段內容。

當輸入字段更改時,我還想更改第二個組件中的內容。非常簡單,但這將為我們完成工作。

介紹我們需要的新組件

我刪除了 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.js 文件,我們向名為 的商店添加一個屬性state,它是一個包含該flavor屬性的對象。那最初是一個空字符串。

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

Vue.use(Vuex)

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

當用戶輸入輸入字段時,我們將更新它。

添加突變

除非使用突變,否則無法操縱狀態。我們設置了一個將在 Form 組件中使用的變更來通知商店狀態應該改變。

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 來引用狀態屬性

有了這個集合,我們需要添加一種查看狀態的方法。我們使用getter 來做到這一點。我們為該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商店添加到應用程序

現在該商店已準備就緒,可以使用了。我們回到我們的應用程序代碼,在 main.js 文件中,我們需要導入狀態并使其在我們的 Vue 應用程序中可用。

我們增加

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

我們將它添加到 Vue 應用程序中:

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

一旦我們添加了它,因為這是主要的 Vue 組件,store每個 Vue 組件內的變量都將指向 Vuex 存儲。

使用提交更新用戶操作的狀態

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

我們通過使用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>

現在我們有了風味的價值,我們使用 Vuex API:

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

看看我們如何使用this.$store??這要歸功于在主要Vue組件初始化中包含了存儲對象。

commit()方法接受一個突變名稱(我們change在Vuex存儲中使用了)和一個有效負載,這些負載將作為回調函數的第二個參數傳遞給該突變。

使用 getter 打印狀態值

現在我們需要在 Display 模板中引用這個值的 getter,使用$store.getters.flavor.?this可以刪除,因為我們在模板中,并且this是隱式的。

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

包起來

Vuex 的介紹到此結束!