工程建設(shè)采購(gòu)有哪些網(wǎng)站今天特大新聞最新消息
什么是依賴注入
個(gè)人的理解 : 依賴注入,是在 一顆 組件樹中,由 【前代組件】 給 【后代組件】 提供 屬性值的 一種方式 ;這種方式 突破了 【父子組件】之間通過 props 的方式傳值的限制,只要是 【前代組件】提供的 依賴,【后代組件】都可以執(zhí)行注入使用;我愿稱之為 【跨代傳值】。
依賴注入使用到的 關(guān)鍵方法:
provide()
: 提供依賴
inject()
: 注入依賴
依賴注入使用的注意事項(xiàng)
1、依賴注入的組件 ,必須是 一棵組件樹的 前后代關(guān)系,兄弟組件不支持;
2、不建議后代組件中直接修改 注入的依賴的值,建議 前代組件中 將修改依賴的方法一并暴露出去;
3、依賴注入支持 全局的注入(這個(gè)較為特殊一些);
借用官網(wǎng)的一張圖就是下面的樣子:
依賴注入的使用方式
1、注入普通值 : 直接指定 key 和 value
2、注入響應(yīng)式的值 : 注入的值是一個(gè) 響應(yīng)式的對(duì)象
3、注入時(shí)提供默認(rèn)值 :inject() 方法 第二個(gè)參數(shù)可以指定默認(rèn)值,當(dāng)沒有提供依賴時(shí) 展示的時(shí)默認(rèn)值
4、限制 提供的數(shù)據(jù)不能被 后代修改 : 使用 readonly 進(jìn)行限制
5、同時(shí)提供響應(yīng)式的修改方法
6、全局提供依賴 ; 可以在 app 中進(jìn)行全局提供依賴,所有的組件都可以注入依賴
7、使用 Symbol() 的方式指定 key
8、給 依賴注入 提供 類型約束下面對(duì)上述的清醒進(jìn)行案例介紹:
1、注入普通值
provide(key,value)
: 提供依賴
const value = inject(key)
: 注入依賴
前代組件 : 提供依賴
<template><div class="basediv">APP.vue 中的 msg : {{ msg }}<br><br><!-- 引入子組件 --><ChildComponent /></div></template><script setup lang="ts">// 引入 provide 方法import { ref,provide } from 'vue'// 引入子組件import ChildComponent from './ChildComponent.vue'// 聲明父組件的一個(gè)變量const msg = ref('這是父組件的msg變量')// 提供一個(gè)普通的依賴對(duì)象provide('key1','key1 的值')</script><style scoped>.basediv{width: 600px;height: 400px;border: 1px solid red;}
</style>
后代組件 : 注入依賴
<template><!-- 子組件 --><div class="childdiv">子組件 - msg : {{ msg }}<br>注入的普通的依賴值 :{{ key1Value }}</div></template><script setup lang="ts">// 引入 inject 方法import { ref,inject } from 'vue'// 聲明一個(gè)變量const msg = ref('這是子組件的msg變量')// 注入依賴 - 普通的數(shù)據(jù)const key1Value = inject('key1')console.log('后代組件中接收到的 key1 的值 : ',key1Value)</script><style scoped>.childdiv{width: 350px;border: 1px solid green;}</style>
運(yùn)行效果:
2、注入響應(yīng)式的值
前代組件 : 提供依賴
<template><div class="basediv">APP.vue 中的 msg : {{ msg }}<br> APP.vue 中的 abc : {{ abc }}<br><br><!-- 引入子組件 --><ChildComponent /></div></template><script setup lang="ts">// 引入 provide 方法import { ref,provide } from 'vue'// 引入子組件import ChildComponent from './ChildComponent.vue'// 聲明父組件的一個(gè)變量const msg = ref('這是父組件的msg變量')// 提供一個(gè)響應(yīng)式的依賴對(duì)象const abc = ref(1001)provide('key2',abc)</script><style scoped>.basediv{width: 600px;height: 400px;border: 1px solid red;}
</style>
后代組件 : 注入依賴
<template><!-- 子組件 --><div class="childdiv">子組件 - msg : {{ msg }}<br>注入的響應(yīng)式依賴 :{{ key2Value }}</div></template><script setup lang="ts">// 引入 inject 方法import { ref,inject} from 'vue'// 聲明一個(gè)變量const msg = ref('這是子組件的msg變量')// 注入依賴-響應(yīng)式的依賴const key2Value = inject('key2') console.log('后代組件中接收到的 key2 的值 :',key2Value)</script><style scoped>.childdiv{width: 350px;border: 1px solid green;}</style>
運(yùn)行效果:
3、注入依賴時(shí)寫一個(gè)默認(rèn)值
后代組件 在進(jìn)行 依賴注入時(shí),如果前代組件沒有 提供依賴,則可以只用默認(rèn)值進(jìn)行代替
默認(rèn)值 是inject()
方法的第二個(gè)參數(shù)
前代組件 :
不
提供依賴
<template><div class="basediv">APP.vue 中的 msg : {{ msg }}<br> <br><!-- 引入子組件 --><ChildComponent /></div></template><script setup lang="ts">// 引入 provide 方法import { ref,provide } from 'vue'// 引入子組件import ChildComponent from './ChildComponent.vue'// 聲明父組件的一個(gè)變量const msg = ref('這是父組件的msg變量')</script><style scoped>.basediv{width: 600px;height: 400px;border: 1px solid red;}
</style>
后代組件 : 注入依賴
<template><!-- 子組件 --><div class="childdiv">子組件 - msg : {{ msg }}<br>注入的響應(yīng)式依賴 :{{ key2Value }}</div></template><script setup lang="ts">// 引入 inject 方法import { ref,inject,toRef } from 'vue'// 聲明一個(gè)變量const msg = ref('這是子組件的msg變量')// 注入依賴-響應(yīng)式的依賴const key2Value = inject('key2','key2的默認(rèn)值') console.log('后代組件中接收到的 key2 的值 :',key2Value)</script><style scoped>.childdiv{width: 350px;border: 1px solid green;}</style>
運(yùn)行效果:
4、提供響應(yīng)式的修改方法
前代組件 : 提供依賴
此時(shí)提供的依賴是 一個(gè)對(duì)象
的形式 :包含數(shù)據(jù)
和方法
<template><div class="basediv">APP.vue 中的 msg : {{ msg }}<br> APP.vue 中的 abc : {{ abc }}<br><!-- 引入子組件 --><ChildComponent /></div></template><script setup lang="ts">// 引入 provide 方法import { ref,provide } from 'vue'// 引入子組件import ChildComponent from './ChildComponent.vue'// 聲明父組件的一個(gè)變量const msg = ref('這是父組件的msg變量')// 提供一個(gè)響應(yīng)式的依賴對(duì)象const abc = ref(1001)// 提供修改的方法const changeABC = ()=>{console.log('App 中修改 abc 的值為 888');abc.value = 888;}// 提供 依賴對(duì)象 和 方法provide('key2',{abc,changeABC})</script><style scoped>.basediv{width: 600px;height: 400px;border: 1px solid red;}
</style>
后代組件 : 注入依賴
<template><!-- 子組件 --><div class="childdiv">子組件 - msg : {{ msg }}<br>注入的響應(yīng)式依賴 :{{ key2Value }}<br><button @click="changeAbcFromHd">修改 abc 的值</button></div></template><script setup lang="ts">// 引入 inject 方法import { ref,inject} from 'vue'// 聲明一個(gè)變量const msg = ref('這是子組件的msg變量')// 注入依賴-響應(yīng)式的依賴const key2Value = inject('key2') console.log('后代組件中接收到的 key2 :',key2Value)// 點(diǎn)擊按鈕修改 依賴的值const changeAbcFromHd = ()=>{key2Value.changeABC();}</script><style scoped>.childdiv{width: 350px;border: 1px solid green;}</style>
運(yùn)行效果: 注意觀察點(diǎn)擊前后的 數(shù)據(jù)狀態(tài)的變化
初始頁(yè)面 | 點(diǎn)擊按鈕后 |
---|---|
![]() | ![]() |
5、readonly 限制修改
當(dāng)想限制傳遞的依賴只能是只讀時(shí),需要使用
readonly
關(guān)鍵字進(jìn)行限制;
注意 : 只能是針對(duì) 沒有提供修改函數(shù)的依賴,如果該依賴提供了修改函數(shù),通過修改函數(shù)觸發(fā)的修改仍然是有效的。
前代組件 : 提供依賴 : 一個(gè)普通的,一個(gè)只讀的
<template><div class="basediv">APP.vue 中的 msg : {{ msg }}<br> APP.vue 中的 abc : {{ abc }}<br>APP.vue 中的 xyz : {{ xyz }}<br><!-- 引入子組件 --><ChildComponent /></div></template><script setup lang="ts">// 引入 provide 方法import { ref,provide,readonly } from 'vue'// 引入子組件import ChildComponent from './ChildComponent.vue'// 聲明父組件的一個(gè)變量const msg = ref('這是父組件的msg變量')// 提供一個(gè)普通的依賴對(duì)象// provide('key1','key1 的值')// 提供一個(gè)響應(yīng)式的依賴對(duì)象const abc = ref(1001)const xyz = ref(2002)// 提供 依賴對(duì)象provide('key2',abc)// 提供一個(gè)只讀的依賴對(duì)象provide('key3',readonly(xyz))</script><style scoped>.basediv{width: 600px;height: 400px;border: 1px solid red;}
</style>
后代組件 : 注入依賴
<template><!-- 子組件 --><div class="childdiv">子組件 - msg : {{ msg }}<br><!-- 注入的普通的依賴值 :{{ key1Value }} --><!-- <br> -->注入的響應(yīng)式依賴key2 :{{ key2Value }}<br>注入的響應(yīng)式依賴key3 :{{ key3Value }}<br></div></template><script setup lang="ts">// 引入 inject 方法import { ref,inject } from 'vue'// 聲明一個(gè)變量const msg = ref('這是子組件的msg變量')// 注入依賴-響應(yīng)式的依賴const key2Value = inject('key2') console.log('后代組件中接收到的 key2 :',key2Value)const key3Value = inject('key3') console.log('后代組件中接收到的 key3 :',key2Value)// 延遲10s 執(zhí)行修改console.log(new Date())setTimeout(() => {console.log(new Date(), '開始執(zhí)行 依賴值的修改' )key2Value.value = 666;key3Value.value = 888;}, 10000);</script><style scoped>.childdiv{width: 350px;border: 1px solid green;}</style>
運(yùn)行效果:
6、全局提供依賴
main.js : 提供全局依賴
import { createApp } from 'vue'// 根組件
import App from './App.vue'// 創(chuàng)建應(yīng)用實(shí)例
const app = createApp(App)// 直接注入一個(gè)全局的 依賴
app.provide('globalKey1','全局的變量值1')// 掛在應(yīng)用,渲染頁(yè)面,這一步應(yīng)該是在最后執(zhí)行的
app.mount("#app")
后代組件 : 注入依賴
<template>
</template><script setup lang="ts">// 引入 inject 方法import { inject } from 'vue'const globalValue = inject('globalKey1')console.log('組件中注入全局的變量 :',globalValue)</script><style scoped>
</style>
運(yùn)行效果:
7、Symbol() 的方式指定 key
之前我們?cè)谔峁┮蕾嚨臅r(shí)候,都是直接用字符串作為依賴的key,
說實(shí)話,這樣做 一點(diǎn)毛病沒有。
但是,大家不都是講求規(guī)范嘛,Symbol()
就提供了這種方式:
1、寫一個(gè)專門用來聲明 key 的文件;
2、前代組件 引入 key,提供依賴;
3、后代組件 引入 key ,注入依賴。
key 文件
// 聲明 兩個(gè)key
export const KEY1 = Symbol()export const KEY2 = Symbol()
前代組件 : 提供依賴
<template><div class="basediv">APP.vue 中的 msg : {{ msg }}<br> APP.vue 中的 abc : {{ abc }}<br><!-- 引入子組件 --><ChildComponent /></div></template><script setup lang="ts">// 引入 provide 方法import { ref,provide } from 'vue'// 引入子組件import ChildComponent from './ChildComponent.vue'// 聲明父組件的一個(gè)變量const msg = ref('這是父組件的msg變量')// 引入定義的keyimport { KEY1 ,KEY2} from './key';// 提供依賴const abc = ref(1001)provide(KEY1,abc)provide(KEY2,'key2valueladfadfa')</script><style scoped>.basediv{width: 600px;height: 400px;border: 1px solid red;}
</style>
后代組件 : 注入依賴
<template><!-- 子組件 --><div class="childdiv">子組件 - msg : {{ msg }}<br><!-- 注入的普通的依賴值 :{{ key1Value }} --><!-- <br> -->注入的響應(yīng)式依賴key :{{ keyValue }}<br>注入的響應(yīng)式依賴key2 :{{ key2Value }}<br></div></template><script setup lang="ts">// 引入 inject 方法import { ref,inject } from 'vue'// 聲明一個(gè)變量const msg = ref('這是子組件的msg變量')// 引入 key import { KEY1,KEY2 } from './key';// 注入依賴const keyValue = inject(KEY1) const key2Value = inject(KEY2) </script><style scoped>.childdiv{width: 350px;border: 1px solid green;}</style>
運(yùn)行效果:
8、 依賴注入 提供 類型約束
InjectionKey
接口 : 限制 依賴注入的值的類型
key文件
// 從 vue 中 導(dǎo)入 類型
import type { Ref,InjectionKey } from 'vue'// 聲明 key : 指定注入的依賴的值的類型是 Ref
export const KEY1 = Symbol() as InjectionKey<Ref<number>>
// 聲明 key : 指定注入的依賴的值的類型是 string
export const KEY2 = Symbol() as InjectionKey<string>
前代組件 : 提供依賴
<template><div class="basediv">APP.vue 中的 msg : {{ msg }}<br> APP.vue 中的 abc : {{ abc }}<br><!-- 引入子組件 --><ChildComponent /></div></template><script setup lang="ts">// 引入 provide 方法import { ref,provide } from 'vue'// 引入子組件import ChildComponent from './ChildComponent.vue'// 聲明父組件的一個(gè)變量const msg = ref('這是父組件的msg變量')// 引入定義的keyimport { KEY1 ,KEY2} from './key';// 提供依賴const abc = ref(1001)// 提供一個(gè)響應(yīng)式的對(duì)象依賴provide(KEY1,abc) // 提供一個(gè) 普通的 string 對(duì)象provide(KEY2,'key2valueladfadfa')</script><style scoped>.basediv{width: 600px;height: 400px;border: 1px solid red;}
</style>
后代組件 : 注入依賴
<template><!-- 子組件 --><div class="childdiv">子組件 - msg : {{ msg }}<br><!-- 注入的普通的依賴值 :{{ key1Value }} --><!-- <br> -->注入的響應(yīng)式依賴key :{{ keyValue }}<br>注入的響應(yīng)式依賴key2 :{{ key2Value }}<br></div></template><script setup lang="ts">// 引入 inject 方法import { ref,inject } from 'vue'// 引入 Ref 類型import type { Ref } from 'vue';// 聲明一個(gè)變量const msg = ref('這是子組件的msg變量')// 引入 key import { KEY1,KEY2 } from './key';// 注入依賴 : 同樣可以使用泛型指定類型const keyValue = inject<Ref<number>>(KEY1) const key2Value = inject<string>(KEY2,"默認(rèn)值") </script><style scoped>.childdiv{width: 350px;border: 1px solid green;}</style>
運(yùn)行效果:
至此,依賴注入的使用就完成了。