父傳更深的后代
一般往深度層級傳遞值,有這兩種方式:
· provide / inject
· vuex
provide / inject
一看到“深”這個字,大家肯定第一想到的就Vue2中的provide / inject選項。沒錯,這套邏輯在vue3中同樣適用,這兩個選項變成了兩個方法。
provide允許我們向當前組件的所有后代組件,傳遞一份數據,所有后代組件能夠通過inject這個方法來決定是否接受這份數據。
大致的示意圖如下:
實際應用場景
主要應用的場景有兩中,一種深度傳遞一個參數或者一個函數的時候,另一種是給插槽上不確定性的組件傳參的時候。
重點說一下給插槽上的組件傳參。先實現一個最外層的ValidateForm組件,它主要負責接受一整個表單數據和整個表單數據的校驗規則。其內部提供了一個插槽,用於放置一些不確定性的組件。還有一個ValidateFormItem組件可以接受一個字段名,通過這字段名准確知道需要校驗哪個字段(tips:功能其實和element-ui類似)。
組件化開發,需要將參數和功能進行解耦,所以我們這樣來設計:
ValidateForm:model,rules,只管接受整份表單的數據和校驗規則
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去效驗某個字段,那它就需要拿到那份表單的數據,通過formData[prop]去取到那個字段的值,那這份formData從哪里來呢?首先不可能每寫一個ValidateFormItem組件都傳遞一份。因為,實際開發中我們並不能確定在ValidateForm下要寫多少個ValidateFormItem組件,如果每寫一個都手動傳遞一份表單的數據,這些寫起來就會多了很多冗余的代碼而且也很麻煩。所以,就由ValidateForm這個組件獨立接受並分發下來。
ValidateForm
所以我們需要ValidateForm來向下分發數據。
<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) {
// 向后代發放數據
provide(modelKey, props.model)
provide(rulesKey, props.rules)
return {}
}
})
</script>
ValidateFormItem
ValidateFormItem接受上面傳遞的數據。
<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傳下來的數據
const model = inject<any>(modelKey, ref({}))
const rules = inject<any>(rulesKey, ref({}))
// 根據props.prop在model和rules分別取出需要 校驗的數據 和 校驗的規則
console.log(model[props.prop])
console.log(rules[props.prop])
// 數據校驗的邏輯
return {
//...
}
}
})
</script>
provide / inject總結
在這篇文章Vue組件通信方式及其應用場景總結中,大佬對其的優缺點已經總結很好了。這里提一下它的缺點,就是不能解決兄弟組件的通信。
這里的provide和inject我也只是了解,在我的項目中並沒有實際應用,我使用的reactive替代vuex的方式來實現更深層次的組件傳值。這個后邊會介紹。
有好的建議,請在下方輸入你的評論。
歡迎訪問個人博客
https://guanchao.site
歡迎訪問小程序: