有没有办法在Vue 3动态组件中声明主机设置函数之外的provide/inject?

e0bqpujr  于 2023-02-24  发布在  Vue.js
关注(0)|答案(2)|浏览(122)

我在Vue3中创建了一个dynamic component。我使用v-bind提供了props

<component :is='MyComponent' v-bind='myProps' />

我想使用provide/inject特性。如何将提供的属性导入动态组件?我的动态组件在setup函数中调用inject,并期望其子组件的值为provided
虽然这没有记录在Vue上,但我尝试了以下方法,但没有成功:

<component :is='MyComponent' v-bind='myProps' :provide='myProvidedProps'/>

甚至尝试将provide对象放入props对象中。

fiei3ece

fiei3ece1#

也许你只需要把provided属性注入到需要它的组件中:

const { provide, inject, ref } = Vue
const app = Vue.createApp({
  setup() {
    const MyComponent = ref('child')
    const count = ref(0)
    provide('key', count)
    return { MyComponent, count }
  },
})
app.component('child', {
  template: `<grandchild />`,
})
app.component('grandchild', {
  template: `
    <div>
      <button @click="key++">add child</button>
      {{ key }}
    </div>
  `,
  setup() {
    const key = inject('key')
    return { key }
  }
})
app.mount('#demo')
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
  <button @click="count++">add parent</button>
  {{ count }}
  <component :is='MyComponent' v-bind='myProps' />
</div>
jc3wubiy

jc3wubiy2#

浏览完Vue3源代码后,无法直接在模板中将provide规范指示给dynamic component,必须在动态组件的父组件的设置函数或选项中调用,或者在动态组件的设置或选项中调用。
这两个选项是:
1.在承载动态组件的组件上调用provide

setup() {
  provide('message', 'hello')
}
<template>
  <component :is='myComponent' />
</template>

这对我不起作用,因为我的设置函数在我的动态组件被激活之前就已经被调用了;我还需要同时设置组件类型和提供的值。
1.将要提供的项作为 prop 发送到组件中,并让动态组件对它们调用provide。
一个二个一个一个
我的组件

setup() {
  for(let [key,value] of Object.entries(props.toProvide) ) {
    provide(key, value)
  }
}

现在,这也有它的问题,因为每个动态组件现在都需要负责知道并调用传入的provide项。

溶液

每个组件都需要知道所提供的值,一种绕过这种情况的方法是创建一个提供这些值的中间组件。
可提供(中间组件)

<script setup lang="ts">
import {provide} from 'vue'

const props = defineProps<{
  is: any
  provide?: Record<string, any>
  [key: string]: any
}>()

if (props.provide) {
  for (const [key, value] of Object.entries(props.provide)) {
    provide(key, value)
  }
}

const _props = Object.fromEntries(Object.entries(props).filter(it => {
  return it[0] !== 'is' && it[0] !== 'provide'
}))
</script>

<template>
  <component :is="is" v-bind="_props"/>
</template>

像这样使用它:

<template>
  <providable :is="myComponent" :provide='toProvide' v-bind='myProps' />
</template>

相关问题