1. 程式人生 > 程式設計 >Vue3狀態管理的使用詳解

Vue3狀態管理的使用詳解

背景

隨著vue3的逐步應用,對狀態管理的需求越來越多。起初是基於Vuex4進行狀態管理的,但是Vuex4也暴露了一些問題。從個人角度來說,Vuex4類似於過渡期產品,對TypeScript的支援性並不完整。如果使用TypeScript編寫元件,需要遵循一定步驟後,才可以正確進行型別推斷,並程式設計客棧且對modules的使用上也並不友好。Vuex核心貢獻者Kia King也表示Vuex5已經在計劃中,並且能提供完整的TypeScript支援,那麼在Vuex5面世之前,或者直接"捨棄"Vuex的話有沒有其他狀態管理的方案?

Provide / Inject

provide和injwww.cppcns.com

ect並不是Vue3的新特性,在Vue2中就已經存在了。文件中提到provide和inject繫結並不是可響應的。然而,如果你傳入了一個可監聽的物件,那麼其物件的property還是可響應的。

Vue3在Computed與watch的基礎上新增了響應性API ref和reactive,可以更加方便provide和inject的應用,再結合Composition API的思想,是否能實現一個簡易版的ZtxGiJW狀態管理?

Vue3狀態管理的使用詳解

抽離共享狀態

// 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狀態管理的使用的資料請關注我們其它相關文章!