Vue3狀態(tài)管理的使用詳解
背景
隨著Vue3的逐步應用,對狀態(tài)管理的需求越來越多。起初是基于Vuex4進行狀態(tài)管理的,但是Vuex4也暴露了一些問題。從個人角度來說,Vuex4類似于過渡期產(chǎn)品,對TypeScript的支持性并不完整。如果使用TypeScript編寫組件,需要遵循一定步驟后,才可以正確進行類型推斷,并且對modules的使用上也并不友好。Vuex核心貢獻者Kia King也表示Vuex5已經(jīng)在計劃中,并且能提供完整的TypeScript支持,那么在Vuex5面世之前,或者直接"舍棄"Vuex的話有沒有其他狀態(tài)管理的方案?
Provide / Inject
provide和inject并不是Vue3的新特性,在Vue2中就已經(jīng)存在了。文檔中提到provide和inject綁定并不是可響應的。然而,如果你傳入了一個可監(jiān)聽的對象,那么其對象的property還是可響應的。
Vue3在Computed與watch的基礎上新增了響應性API ref和reactive,可以更加方便provide和inject的應用,再結(jié)合Composition API的思想,是否能實現(xiàn)一個簡易版的狀態(tài)管理?
抽離共享狀態(tài)
// 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 = () => { //數(shù)目 const count = ref<number>(1); //遞增方法 const increase = () => { count.value++; }; //更新方法 const updateCount = (num: number) => { count.value = num; }; //提供的共享狀態(tài)對象 const depends = { count: readonly(count), //狀態(tài)只讀,通過方法進行修改 increase, updateCount }; //使用provide api實現(xiàn)狀態(tài)對象提供 provide(CalculatorSymbol, depends); //返回狀態(tài)對象,讓同級可調(diào)用 return depends; }; //注入方法 export const calculatorInject = () => { //使用inject api注入狀態(tài) const calculatorContext = inject<Calculator>(CalculatorSymbol); //未共享就注入的錯誤校驗 if (!calculatorContext) { throw new Error('Inject must be used affer Provide'); } //返回注入的貢獻狀態(tài) return calculatorContext; };
提供數(shù)據(jù)
相比起Vuex的全局共享,利用Provide / Inject可以實現(xiàn)全局或者局部共享,
全局共享,可以在main.ts中注入全局狀態(tài):
// src/main.ts import { createApp, h } from 'vue'; import App from '@/App.vue'; import { calculatorProvide } from '@/context/calculator'; // 創(chuàng)建vue實例 const app = createApp({ setup() { calculatorProvide(); return () => h(App); } }); // 掛載實例 app.mount('#app');
如果只想局部共享,可以在父組件中注入狀態(tài)
// src/views/parent.vue import { defineComponent } from "vue"; import { calculatorProvide } from '@/context/calculator'; export default defineComponent({ name: "parent", setup() { //共享數(shù)據(jù) calculatorProvide(); } });
注入數(shù)據(jù)
子組件可以通過狀態(tài)注入,使用或修改狀態(tài)
// src/views/child.vue import { defineComponent } from "vue"; import { calculatorInject } from '@/context/calculator'; export default defineComponent({ name: "child", setup() { //注入數(shù)據(jù) const { count, increase, updateCount } = calculatorInject(); } });
小結(jié)
實際上,你可以將依賴注入(Provide / Inject)看作是"long range props",除了:
- 父組件不需要知道哪些子組件使用它provide的property
- 子組件不需要知道inject的property來自哪里
Vue3使依賴注入的使用更加靈活便捷,以此仿造了小型的狀態(tài)管理,個人測試上,對TypeScript的支持性比較完整
reactive
那么不使用Provide / Inject,還有別的方法可以實現(xiàn)狀態(tài)管理嗎?直接上代碼。
抽離共享狀態(tài)
// src/context/calculator.ts type Calculator = { count: number; increase: () => void; updateCount: (num: number) => void; }; //共享狀態(tài) const calculatorStore = reactive<Calculator>({ count: 1, increase: () => { calculatorStore.count++; }, updateCount: (num: number) => { calculatorStore.count = num; } }); export { calculatorStore };
使用共享狀態(tài)
使用狀態(tài)的方法很簡單,只需要import狀態(tài)即可,需要使用狀態(tài)的組件,都需要導入
// src/views/any.vue import { defineComponent } from "vue"; import { calculatorStore } from '@/context/calculator'; export default defineComponent({ name: "any", setup() { console.log(calculatorStore.count); } });
小結(jié)
其實這個方案利用的是reactive的響應性及import同一實例原理,相比起依賴注入來的更簡單粗暴,也能正確支持TypeScript校驗。但是依賴注入可以在不同根節(jié)點共享不同的數(shù)據(jù),而這個reactive方案永遠共享的是一個實例,在某些業(yè)務場景下并不適用。
結(jié)語
首先,Vuex仍舊是更成熟全面的方案,只是針對一些簡單的狀態(tài)管理,可以嘗試換個思路解決;當然以上的方案可能還有很多考慮不全地方,歡迎各位大神指點指點~
以上就是Vue3狀態(tài)管理的使用詳解的詳細內(nèi)容,更多關于Vue3狀態(tài)管理的使用的資料請關注腳本之家其它相關文章!
相關文章
Vue重要修飾符.sync對比v-model的區(qū)別及使用詳解
這篇文章主要為大家介紹了Vue中重要修飾符.sync與v-model的區(qū)別對比及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07Vue組件通信$attrs、$listeners實現(xiàn)原理解析
這篇文章主要介紹了Vue組件通信$attrs、$listeners實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09Vue+Vite項目初建(axios+Unocss+iconify)的實現(xiàn)
一個好的項目開始搭建總是需要配置許多初始化配置,本文就來介紹一下Vue+Vite項目初建(axios+Unocss+iconify)的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-02-02vue項目優(yōu)雅實現(xiàn)自動引入組件的方法詳解
在我們寫vue項目的時候,都會引入一些組件庫,有時候有可能還不止一個組件庫,那么如何優(yōu)雅的實現(xiàn)自動引入組件呢,下面小編就來和大家詳細講講吧2023-09-09vue-electron使用serialport時問題解決方案
這篇文章主要介紹了vue-electron使用serialport時問題解決方案,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-09-09