Vue3狀態管理的使用詳解
背景
隨著vue3的逐步應用,對狀態管理的需求越來越多。起初是基於Vuex4進行狀態管理的,但是Vuex4也暴露了一些問題。從個人角度來說,Vuex4類似於過渡期產品,對TypeScript的支援性並不完整。如果使用TypeScript編寫元件,需要遵循一定步驟後,才可以正確進行型別推斷,並程式設計客棧且對modules的使用上也並不友好。Vuex核心貢獻者Kia King也表示Vuex5已經在計劃中,並且能提供完整的TypeScript支援,那麼在Vuex5面世之前,或者直接"捨棄"Vuex的話有沒有其他狀態管理的方案?
Provide / Inject
provide和injwww.cppcns.com
Vue3在Computed與watch的基礎上新增了響應性API ref和reactive,可以更加方便provide和inject的應用,再結合Composition API的思想,是否能實現一個簡易版的ZtxGiJW狀態管理?
抽離共享狀態
// src/context/calculator.ts import { ref,inject,provide,readonly } from 'vue'; type Calculator = { count: number; increase: () => void; updateCount: (num: number) => void; }; //provide的key,唯一令牌 const CalculatorSymbol = Symbol(); //提供者 export const calculatorProvide = () => { //數目 const count = ref<number>(1); //遞增方法 const程式設計客棧 increase = () => { count.value++; }; //更新方法 const updateCount = (num: number) => { count.value = num; }; //提供的共享狀態物件 const depends = { count: readonly(count),//狀態只讀,通過方法進行修改 increase,updateCount }; //使用provide api實現狀態物件提供 provide(CalculatorSymbol,depends); //返回狀態物件,讓同級可呼叫 return depends; }; //注入方法 export const calculatorInject = () => { //使用inject api注入狀態 const calculatorContext = inject<Calculator>(CalculatorSymbol); //未共享就注入的錯誤校驗 if (!calculatorContext) { throw new Error('Inject must be used affer Provide'); } //返回注入的貢獻狀態 return calculatorContext; };
提供資料
相比起Vuex的全域性共享,利用Provide / Inject可以實現全域性或者區域性共享,
全域性共享,可以在main.ts中注入全域性狀態:
// src/main.ts import { createApp,h } from 'vue'; import App from '@/App.vue'; import { calculatorProvide } from '@/context/calculator'; // 建立vue例項 const app = createApp({ setup() { calculatorProvide(); return () => h(App); } }); // 掛載例項 app.mount('#app');
如果只想區域性共享,可以在父元件中注入狀態
// src/views/parent.vue import { defineComponent } from "vue"; import { calculatorProvide } from '@/context/calculator'; export default defineComponent({ name: "parent",setup() { //共享資料 calculatorProvide(); } });
注入資料
子元件可以通過狀態注入,使用或修改狀態
// src/views/child.vue import { defineComponent } from "vue"; import { calculatorInject } from '@/context/calculator'; export default defineComponent({ name: "child",setup() { //注入資料 const { count,increase,updateCount } = calculatorInject(); } });
小結
實際上,你可以將依賴注入(Provide / Inject)看作是"long range props",除了:
- 父元件不需要知道哪些子元件使用它provide的property
- 子元件不需要知道inject的property來自哪裡
Vue3使依賴注入的使用更加靈活便捷,以此仿造了小型的狀態管理,個人測試上,對TypeScript的支援性比較完整
reactive
那麼不使用Provide / Inject,還有別的方法可以實現狀態管理嗎?直接上程式碼。
抽離共享狀態
// src/context/calculator.ts type Calculator = { count: number; increase: () => void; updateCount: (num: number) => void; }; //共享狀態 const calculatorStore = reactive<Calculator>({ count: 1,increase: () => { calculatorStore.count++; },updateCount: (num: number) => { calculatorStore.count = num; } }); export { calculatorStore };
使用共享狀態
使用狀態的方法很簡單,只需要import狀態即可,需要使用狀態的元件,都需要匯入
// src/viewshttp://www.cppcns.com/any.vue import { defineComponent } from "vue"; import { calculatorStore } from '@/context/calculator'; export default defineComponent({ name: "any",setup() { console.log(calculatorStore.count); } });
小結
其實這個方案利用的是reactive的響應性及import同一例項原理,相比起依賴注入來的更簡單粗暴,也能正確支援TypeScript校驗。但是依賴注入可以在不同根節點共享不同的資料,而這個reactive方案永遠共享的是一個例項,在某些業務場景下並不適用。
結語
首先,Vuex仍舊是更成熟全面的方案,只是針對一些簡單的狀態管理,可以嘗試換個思路解決;當然以上的方案可能還有很多考慮不全地方,歡迎各位大神指點指點~
以上就是Vue3狀態管理的使用詳解的詳細內容,更多關於Vue3狀態管理的使用的資料請關注我們其它相關文章!