做者:Anthony Gore
譯者:前端小智
來源:vuejsdevelopers
有夢想,有乾貨,微信搜索 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。前端
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及個人系列文章。vue
Vuex
是 Vue.js 生態系統中必不可少的工具。可是新接觸 Vuex 的開發人員可能會被諸如「狀態管理模式」這樣的術語所排斥,而且對他們實際須要Vuex的目的感到困惑。git
本文算是 Vuex的入門,固然也會 Vuex 的高級概念,並向你們展現如何在應用程序中使用 Vuex。github
要理解Vuex,首先要理解它要解決的問題。面試
假設咱們開發了一個多用戶聊天應用。界面有用戶列表、私人聊天窗口、帶有聊天記錄的收件箱和通知欄,通知用戶當前未查看的其餘用戶的未讀消息。vuex
數以百萬計的用戶天天經過咱們的應用與數以百萬計的其餘用戶聊天。然而,有人抱怨一個惱人的問題:通知欄偶爾會給出錯誤的通知。用戶被通知有一條新的未讀消息,但當他們查看時,它只是一條已經被看過的消息。npm
該做者所描述的是幾年前 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> <div> <h1>To-Do List</h1> <div> <TodoNew /> <TodoList /> </div> </div> </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/2...
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
有夢想,有乾貨,微信搜索 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及個人系列文章。