在 Vue 過氣前要學的第十六件事 - 愛是雙向的 中,
我們提到了 vue 的雙向綁定,這僅止於父子關係的組件。
但如果今天這個元件跨了兩層,跨了三層嗎,
你還這樣一層一層傳嗎 傳到最後都不知道哪個是哪個了。
這也是你常會看到的 Prop Drilling,
▲prop-drilling 示意圖,Root 代表父元素,Footer 代表子元素,DeepChild 代表孫子元素
你的中間層可能根本用不到這個 prop
但你還是為了使用而傳兩層。
因此我們就可以使用 Provide
& Inject
來解決這個問題,
來看看怎麼用吧。
<script setup>
import { provide } from 'vue'
provide(/* 注入名 */ 'message', /* 值 */ 'hello!')
</script>
string
或是 Symbol
ref
兩個組件屬於先後代關係,必須在同一條依賴鍊上,
如果這兩個組件沒有任何依賴關係,那是吃不到的。
不存在同一條依賴鍊,無法注入( inject
)
即便 Root 跟 Footer 只是父子層關係,但一樣可以使用 provide
/inject
<!-- App.vue ( 父層 ) -->
<script setup>
import { ref,provide } from 'vue';
import Comp from './Comp.vue';
const name = ref('')
provide('name',name)
//提供注入名為 'name' 和期望注入值為 `name` 這個 ref
</script>
<template>
<h1>{{ name }}</h1>
<p>職稱:前端工程師</p>
<input v-model="name" placeholder="請輸入名字"/>
<Comp></Comp> <!-- 使用中間層元件 -->
</template>
<!-- Comp.vue 子層元件 -->
<template>
<ChildComp></ChildComp> <!-- 使用末層元件 -->
<!-- 略 -->
</template>
<!-- Comp.vue 孫子層元件 -->
<script setup>
import { inject } from 'vue';
const name = inject('name')
// 使用 inject 接收注入名 'name' 的值
</script>
<template>
<h1 v-if="name">{{name}}的鐵人賽</h1>
</template>
常見於父子組件 ( 通常傳遞不超過一層 )
常見於同一條依賴鍊 ( 爺傳父傳子皆可 )
常見於狀態管理工具 ( 可無視依賴關係,跨組件傳遞 )
今天我們帶到了依賴注入這個觀念,講解了為何要避免 prop-drilling。
透過程式碼實際體驗一下如何使用 provide
/inject
,
並在最後使用圖解來更好的了解常見的資料溝通是怎麼樣的流向。
依賴注入並不是什麼小叮噹的神奇道具,
其實從上面的圖解你可以知道,儘管我今天只有包一層,
我使用上面三種任一都可以傳遞資料下去。
但為什麼今天要區分,就是因為如果全都塞
Store
或是provide
最後只會亂七八糟,完全沒有資料流可言,追溯來源都成了費力的事。
如果你喜歡這個系列或是想看我發瘋,歡迎按下 訂閱
一起走完這三十天吧。
props-drilling
,什麼情況下會發生 ?provide
/inject
,什麼情況不建議用 provide
/inject
?