Vuex
是 Vue.js 生態系統中必不可少的工具。但是新接觸 Vuex 的開發人員可能會被諸如「狀態管理模式」這樣的術語所排斥,並且對他們實際需要Vuex的目的感到困惑。【相關推薦:《》】
本文算是 Vuex的入門,當然也會 Vuex 的高階概念,並向大家展示如何在應用程式中使用 Vuex。
要理解Vuex,首先要理解它要解決的問題。
假設我們開發了一個多使用者聊天應用。介面有使用者列表、私人聊天視窗、帶有聊天記錄的收件箱和通知欄,通知使用者當前未檢視的其他使用者的未讀訊息。
數以百萬計的使用者每天通過我們的應用與數以百萬計的其他使用者聊天。然而,有人抱怨一個惱人的問題:通知欄偶爾會給出錯誤的通知。使用者被通知有一條新的未讀訊息,但當他們檢視時,它只是一條已經被看過的訊息。
該作者所描述的是幾年前 Facebook 開發人員在其聊天系統中遇到的真實情況。 解決這一問題的過程中 開發人員建立名為 "Flux"的應用程式體系結構。 Flux 構成了Vuex,Redux 和其它類似庫的基礎。
Facebook開發者為「殭屍通知」這個問題,苦苦掙扎了一段時間。他們最終意識到,它的永續性不僅僅是一個簡單的缺陷——它指出了應用程式架構中的一些潛在缺陷。
抽象中最容易理解該缺陷:當應用程式中有多個共用資料的元件時,它們互連的複雜性將增加到無法預測或理解資料狀態的地步。 因此,該應用程式無法擴充套件或維護。
Flux
是一個模式,不是一個庫。我們不能去Github下載 Flux。它是一種類似MVC的設計模式。像Vuex和Redux這樣的庫實現Flux模式的方式與其他框架實現MVC模式的方式相同。
事實上,Vuex並沒有實現Flux的全部,只是一個子集。不過現在不要擔心這個問題,我們關注於理解它所遵循的關鍵原則。
元件可能具有僅需要了解的本地資料。 例如,卷軸在使用者列表元件中的位置可能與其他元件無關。
但是,要在元件之間共用的任何資料(即應用程式資料)都必須儲存在一個單獨的位置,與使用它的元件分開。
這個單一位置稱為 "store"。 元件必須從該位置讀取應用程式資料,並且不能保留其自己的副本以防止衝突或分歧。
import { createStore } from "vuex"; // Instantiate our Vuex store const store = createStore({ // "State" 元件的應用程式資料 state () { return { myValue: 0 }; } }); // 元件從其計算的屬性存取 state const MyComponent = { template: "<div>{{ myValue }}</div>", computed: { myValue () { return store.state.myValue; } } };
元件可以從store
中自由讀取資料。 但是不能更改 store
中的資料,至少不能直接更改。
取而代之的是,它們必須告知 store
要更改資料的意圖,store
由負責通過一組定義的功能(稱為mutation
)進行更改。
為什麼採用這種方法? 如果我們集中資料更改邏輯,那麼在狀態不一致的情況下,我們只需要在同一地方排查就行了,不用到具體的每個檔案中。 我們將某些隨機元件(可能在第三方模組中)以意外方式更改資料的可能性降至最低。
const store = createStore({ state() { return { myValue: 0 }; }, mutations: { increment (state, value) { state.myValue += value; } } }); // 需要更新值嗎? // 錯誤的,不要直接更改 store 值 store.myValue += 10; // 正確的,呼叫正確的 mutations。 store.commit('increment', 10);
如果應用程式在其體系結構中實現了上述兩個原則,那麼偵錯資料不一致就容易得多。可以記錄提交併觀察狀態如何變化(在使用Vue Devtools 時確實可以這樣做)。
但如果我們的mutation
被非同步呼叫,這種能力就會被削弱。我們知道提交的順序,但我們不知道元件提交它們的順序。
同步mutation
可確保狀態不取決於不可預測事件的順序和時間。
有了所有這些背景知識,我們終於可以解決這個問題-Vuex 是一個庫,可幫助我們在Vue應用程式中實現Flux架構。 通過執行上述原則,即使在多個元件之間共用資料時,Vuex 仍可將我們的應用程式資料保持在透明且可預測的狀態。
現在,我們已經對Vuex有了一個高階的瞭解,我們看看如何在實際專案建立基於Vuex的應用程式。
為了演示Vuex的用法,我們設定一個簡單的待辦應用程式。 大家可以在此處存取程式碼的有效範例。
範例地址:https://codesandbox.io/s/happ...
如果大家自己的電腦嘗試一波,那麼可以使用下面的命令:
vue create vuex-example
cd vuex-example npm i -S vuex@4 npm run serve
現在,建立 Vuex store,在專案中建立 src/store/index.js
:
mkdir src/store touch src/store/index.js
開啟檔案並匯入createStore
方法。此方法用於定義store
及其特性。現在,我們匯出該store
,以便在Vue應用中能存取它。
// src/store/index.js import { createStore } from "vuex"; export default createStore({});
為了可以從任何元件中存取 Vuex store,我們需要在主檔案中匯入 store
模組,並將store
作為外掛安裝在主Vue範例上
// src/main.js import { createApp } from "vue"; import App from "@/App"; import store from "@/store"; const app = createApp(App); app.use(store); app.mount("#app");
如上所述,Vuex 的重點是通常在大型應用程式中建立可延伸的全域性狀態。 但是,我們可以在一個簡單的待辦應用程式中演示其功能。
完成後效果如下所示:
現在,刪除 HelloWorld 檔案:
rm src/components/HelloWorld.vue
現在,新增一個新元件 TodoNew
,它負責建立新的待辦事項。
touch src/components/TodoNew.vue
開啟 TodoNew.vue
並輸入以下內容:
// src/components/TodoNew.vue <template> <form @submit.prevent="addTodo"> <input type="text" placeholder="Enter a new task" v-model="task" /> </form> </template>
現在轉到元件定義,有兩個區域性狀態屬性-task
和給新待辦事項提供唯一識別符號的id
。
// src/components/TodoNew.vue <template>...</template> <script> export default { data() { return { task: "", id: 0 }; }, methods: { addTodo: function() { // } } }; </script>
過會,我們會建立一個顯示待辦事項的元件。 由於它和TodoNew
元件都需要存取相同的資料,因此這是我們在 Vuex 儲存中儲存的全域性state
的理想選擇。
現在,回到state
並定義屬性狀態。 這裡使用 Vux4 提供的 createStore
函數,該函數返回一個物件。 該物件具有一個屬性 todos
,它是一個空陣列。
// src/store/index.js import { createStore } from "vuex"; export default createStore({ state () { return { todos: [] } } });
從原則2可以知道,Vuex state 不能直接更改,需要定義mutator
函數。
現在,我們向store
新增一個mutation
屬性,並新增一個函數屬性addTodo
。 所有mutator
方法第一個引數。 第二個可選引數是 store,第二個是傳遞的資料。
// src/store/index.js import { createStore } from "vuex"; export default createStore({ state () { return { todos: [] } }, mutations: { addTodo (state, item) { state.todos.unshift(item); } } });
mutation
現在,可以在TodoNew
元件中使用它,在 TodoNew
元件定義一個addTodo
方法。
要存取store
,我們可以使用全域性屬性this.$store
。 使用commit
方法建立一個新的mutation
。 需要傳遞了兩個引數-首先是mutation
的名稱,其次是我們要傳遞的物件,是一個新的待辦事項(由id
和task
值組成)。
// src/components/TodoNew.vue methods: { addTodo: function() { const { id, task } = this; this.$store.commit("addTodo", { id, task }); this.id++; this.task = ""; } }
到目前為止:
使用者將待辦事項通過輸入框輸入,並繫結到 task
變數。
提交表單後,將呼叫addTodo
方法
建立一個待辦事項物件並將其「提交」到store
中。
// src/components/TodoNew.vue <template> <form @submit.prevent="addTodo"> <input type="text" placeholder="Enter a new task" v-model="task" /> </form> </template> <script> export default { data() { return { task: "", id: 0 }; }, methods: { addTodo: function() { const { id, task } = this; this.$store.commit("addTodo", { id, task }); this.id++; this.task = ""; } } }; </script>
現在,我們已經建立了用於新增待辦事項的功能。 接下來,就是把它們顯示出來。
建立一個新元件TodoList.vue
檔案。
touch src/components/TodoList.vue
內容如下:
// src/components/TodoList.vue <template> <ul> <li v-for="todo in todos" :key="todo.id" > {{ todo.description }} </li> </ul> </template>
todos
是一個計算屬性,我們在其中返回Vuex store 的內容。
// src/components/TodoList.vue <script> export default { computed: { todos() { // } } }; </script>
與直接存取store
內容不同,getter
是類似於儲存的計算屬性的函數。在將資料返回到應用程式之前,這些工具非常適合過濾或轉換資料。
例如,下面有getTodos
,它返回未過濾的狀態。 在許多情況下,可以使用filter
或map
來轉換此內容。
todoCount
返回todo
陣列的長度。
通過確保元件願意保留資料的本地副本,getter
有助於實現原則1,即單一資料來源。
// src/store/index.js export default createStore({ ... getters: { getTodos (state) { return state.todos; }, todoCount (state) { return state.todos.length; } } })
返回TodoList
元件,我們通過返回this.$store.getters.getTodos
來完成功能。
// src/components/TodoList.vue <script> export default { computed: { todos() { return this.$store.getters.getTodos; } } }; </script>
App.vue
要完成此應用程式,現在要做的就是匯入並在App.vue
中宣告我們的元件。
// src/App.vue <template> <p> <h1>To-Do List</h1> <p> <TodoNew /> <TodoList /> </p> </p> </template> <script> import TodoNew from "@/components/TodoNew.vue"; import TodoList from "@/components/TodoList.vue"; export default { components: { TodoNew, TodoList } }; </script>
顯然,在大型應用程式中,擁有全域性狀態管理解決方案將有助於讓我們的應用程式可預測和可維護。
但對於比較小的專案,有時候覺得使用 Vuex 太大材小用了,還這個還是大家跟著實際需求走比較合理。
Vuex的優點:
Vuex的缺點:
英文原文地址:https://vuejsdevelopers.com/2017/05/15/vue-js-what-is-vuex/
作者:Anthony Gore
轉載地址:https://segmentfault.com/a/1190000039872016
更多程式設計相關知識,請存取:!!
以上就是什麼是Vuex?Vuex 4初學者指南的詳細內容,更多請關注TW511.COM其它相關文章!