父傳更深的后代
一般往深度層級傳遞值,有這兩種方式:
· provide / inject
· vuex
provide / inject
一看到“深”這個字,大家肯定第一想到的就Vue2中的provide / inject選項。沒錯,這套邏輯在vue3中同樣適用,這兩個選項變成了兩個方法。
provide允許我們向當(dāng)前組件的所有后代組件,傳遞一份數(shù)據(jù),所有后代組件能夠通過inject這個方法來決定是否接受這份數(shù)據(jù)。
大致的示意圖如下:

實際應(yīng)用場景
主要應(yīng)用的場景有兩中,一種深度傳遞一個參數(shù)或者一個函數(shù)的時候,另一種是給插槽上不確定性的組件傳參的時候。
重點說一下給插槽上的組件傳參。先實現(xiàn)一個最外層的ValidateForm組件,它主要負(fù)責(zé)接受一整個表單數(shù)據(jù)和整個表單數(shù)據(jù)的校驗規(guī)則。其內(nèi)部提供了一個插槽,用于放置一些不確定性的組件。還有一個ValidateFormItem組件可以接受一個字段名,通過這字段名準(zhǔn)確知道需要校驗?zāi)膫€字段(tips:功能其實和element-ui類似)。
組件化開發(fā),需要將參數(shù)和功能進行解耦,所以我們這樣來設(shè)計:
ValidateForm:model,rules,只管接受整份表單的數(shù)據(jù)和校驗規(guī)則
ValidateFormItem:prop,只管接受字段名,只需知道自己需要驗證哪一個字段
<template>
<ValidateForm ref="validateFormRef" :model="formData" :rules="rules">
<ValidateFormItem label="用戶名" prop="keyword">
<!-- field組件 -->
</ValidateFormItem>
<ValidateFormItem label="密碼" prop="password">
<!-- field組件 -->
</ValidateFormItem>
</ValidateForm>
</template>
如果ValidateFormItem組件需要通過prop去效驗?zāi)硞€字段,那它就需要拿到那份表單的數(shù)據(jù),通過formData[prop]去取到那個字段的值,那這份formData從哪里來呢?首先不可能每寫一個ValidateFormItem組件都傳遞一份。因為,實際開發(fā)中我們并不能確定在ValidateForm下要寫多少個ValidateFormItem組件,如果每寫一個都手動傳遞一份表單的數(shù)據(jù),這些寫起來就會多了很多冗余的代碼而且也很麻煩。所以,就由ValidateForm這個組件獨立接受并分發(fā)下來。
ValidateForm
所以我們需要ValidateForm來向下分發(fā)數(shù)據(jù)。
<template>
<form>
<slot></slot>
</form>
</template>
<script lang="ts">
import { defineComponent, provide } from 'vue'
export const modelKey = Symbol()
export const rulesKey = Symbol()
export default defineComponent({
name: 'ValidateForm',
props: {
model: {
type: Object
},
rules: {
type: Object
}
},
setup(props) {
// 向后代發(fā)放數(shù)據(jù)
provide(modelKey, props.model)
provide(rulesKey, props.rules)
return {}
}
})
</script>
ValidateFormItem
ValidateFormItem接受上面?zhèn)鬟f的數(shù)據(jù)。
<script lang="ts">
import { defineComponent, reactive, inject, provide } from 'vue'
import { modelKey, rulesKey } from './ValidateForm.vue'
export default defineComponent({
name: 'ValidateFormItem',
props: {
label: String,
required: {
type: Boolean,
default: false
},
prop: String
},
setup(props) {
// 接受ValidateForm傳下來的數(shù)據(jù)
const model = inject<any>(modelKey, ref({}))
const rules = inject<any>(rulesKey, ref({}))
// 根據(jù)props.prop在model和rules分別取出需要 校驗的數(shù)據(jù) 和 校驗的規(guī)則
console.log(model[props.prop])
console.log(rules[props.prop])
// 數(shù)據(jù)校驗的邏輯
return {
//...
}
}
})
</script>
provide / inject總結(jié)
在這篇文章Vue組件通信方式及其應(yīng)用場景總結(jié)中,大佬對其的優(yōu)缺點已經(jīng)總結(jié)很好了。這里提一下它的缺點,就是不能解決兄弟組件的通信。
這里的provide和inject我也只是了解,在我的項目中并沒有實際應(yīng)用,我使用的reactive替代vuex的方式來實現(xiàn)更深層次的組件傳值。這個后邊會介紹。
有好的建議,請在下方輸入你的評論。
歡迎訪問個人博客
https://guanchao.site