前言
現在有比 Vuex 更精簡的狀態管理工具 Pinia,官方也推薦使用。
Pinia 支援 Options API
與 Composition API
,並且完整支援 TypeScript。
但考慮到工作上可能會遇到還是使用 Vuex 的公司或狀況,所以決定學習 Vuex。
Vuex 是什麼?
首先為什麼需要 Vuex?
Vue.js 的最小功能單位是「元件」,每個元件都有自己的狀態(state)、模板(view)以及邏輯(actions),並且會希望元件可以高度重複利用。但隨著專案的成長擴大,元件的增加,容易造成元件與元件之間相互依賴性提高,這時為了保持元件在「高內聚,低耦合」(high cohesion, low coupling)的狀態,也就是元件間的依賴程度降低,每個元件都是獨立的狀態。這樣一來,元件就可以根據不同的程式去被改變與修改,並且不會因此影響到元件本身的功能。
舉例來說,購物車的商品資料可能會在導覽列、產品列表頁面、單一產品頁面、購物車頁面、結帳頁面、完成訂單頁面使用和修改,如果今天在產品列表頁面將購物車商品的數量加 1,這時所有用到購物車商品資料的元件都需要一一去做更新,也就是可能需要將資料一一向上 emit 到根元件,再從根元件向下 props 到每個需要更新的子元件去,這樣不僅增加了元件間的耦合性,也造成日後要維護時的難度。
而 Vuex 就是來解決這個問題的,它是專門為 Vue.js 設計的狀態管理庫,採用集中式存儲管理應用的所有元件狀態。
也就是把共同狀態全都集中到一個 store 去管理,並且只能使用指定的方法去修改裡面資料。
註:如果是小型網站可以單純使用 store 模式。
開始之前我們在稍微來看一下放在 Vuex 官方文件的圖:
Vuex 是作為一個「單一資訊來源(Single Source of Truth)」,也就是將共用資料集中到一個地方去做管理,所以一個應用程式裡只能有一個 store 實體。
Vuex 的主要結構為:
- state:存放資料狀態的物件,類似元件中的 data
- actions:存放方法的物件,除了改變資料狀態以外的方法都會放到這裡,類似
methods
- mutations:負責存放會改變資料的方法
- getters:取得資料狀態的方法,類似
coumputed
安裝 Vuex
用 CDN 引入:
<script src="/path/to/vuex.js"></script>
使用 npm:
npm install vuex@next --save
或是 yarn:
yarn add vuex@next --save
如果是用 Vue CLI:
- 新啟動的專案可以在安裝選項那邊將 Vuex 選起來。
- 如果想再已建立好的專案上安裝可以使用下列指令:
vue add vuex
開始使用 Vuex
在安裝好之後我們可以在自己的專案上導入 Vuex。
- CDN 的方式
import { createApp } from 'vue'
import { createStore } from 'vuex'
const store = createStore({
state: {
},
mutations: {
},
});
const app = createApp({ /* 根元件 */ });
app.use(store);
app.mount('#app');
我們可以用 store.state
去取得 store 裡面的資料,並用 store.commit
來觸發 mutations 去更新 state。
- Vue CLI
如果是使用 Vue CLI 安裝的話,會發現它已經很貼心的幫你在 main.js 引入以及新增了一個 store 目錄,在目錄裡面有一個 index.js 打開如下:
import { createStore } from 'vuex';
export default createStore({
state: {
},
gatters: {
},
mutations: {
},
actions: {
},
modules: {
},
});
在 Vue 元件中我們可以使用 this.$store
來訪問 store 實體,例如:
methods: {
increment() {
this.$store.commit('incrementt');
console.log(this.$store.state.count);
},
},
當然我們也可以選擇不用 use 來導入 store,改成在需要使用的元件內 import 就好:
<template>
...
</template>
<script>
import store from '@/store';
export default {
methods: {
increment() {
store.commit('increment');
},
},
};
</script>
引入 store 的方式就變得跟使用 CDN 一樣。
參考資料
- Vuex 官方文件
- [Vue] Vuex 是什麼? 怎麼用? — State、Mutations (1/5)
- 許國政(Kuro),《重新認識 Vue.js:008 天絕對看不完的 Vue.js 3 指南》