VUE3(十二)provide和inject函數(shù)

父傳更深的后代
一般往深度層級傳遞值,有這兩種方式:
· provide / inject
· vuex

provide / inject

一看到“深”這個字,大家肯定第一想到的就Vue2中的provide / inject選項。沒錯,這套邏輯在vue3中同樣適用,這兩個選項變成了兩個方法。

provide允許我們向當(dāng)前組件的所有后代組件,傳遞一份數(shù)據(jù),所有后代組件能夠通過inject這個方法來決定是否接受這份數(shù)據(jù)。

大致的示意圖如下:

1.png

實際應(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容