Is there a way to declare provision/injection in a Vue3 dynamic component outside of the host settings function?
P粉384366923
P粉384366923 2023-08-30 09:41:50
0
1
487
<p>I'm creating a <code>Dynamic Component</code> in <code>Vue3</code>. I use <code>v-bind</code> to provide <code>props</code>. </p> <pre class="lang-js prettyprint-override"><code><component :is='MyComponent' v-bind='myProps' /> </code></pre> <p>I want to provide/inject</code> functionality using <code>. How can I put the properties I provide into the dynamic component. My dynamic component calls <code>inject</code> in the <code>setup</code> function and expects a </code> value for its child component <code>. </p> <p>While this is not documented on Vue, I tried it without success: </p> <pre class="brush:php;toolbar:false;"><component :is='MyComponent' v-bind='myProps' :provide='myProvidedProps'/></pre> <p>Even tried putting the <code>provide</code> object into the <code>props</code> object. </p>
P粉384366923
P粉384366923

reply all(1)
P粉122932466

After browsing the Vue3 source code, there is no way to providespecifications directly in the template to dynamic components. It must be called in the settings function or options of the parent hosting the dynamic component, or in the settings or options of the dynamic component.

The two options are:

  1. You call provide on the component that hosts the dynamic component.
setup() {
  provide('message', 'hello')
}
<template>
  <component :is='myComponent' />
</template>

This doesn't work for me because my setter function is called before my dynamic component is activated; I also need the component type to be set along with the provided value.

  1. Send the items to be provided as props to the component and let the dynamic component call them.
function setComponent(someImportedComponent, providedValues) {
  myComponent.value = someImportedComponent
  myProps.value = {
    toProvide: providedValues
  }
}
<template>
  <component :is='myComponent' v-bind='myProps' />
</template>

My component

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

Now this has its problems, as each dynamic component now needs to be responsible for understanding and calling the incoming provider.

Solution 1

The solution to each component needing to know the value provided is to create an intermediate component that provides the value.

Available (intermediate components)

<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>

Use it like this:

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

Solution 2

A cleaner solution is to create a wrapper component, similar to how keep-alive works. The target component only needs to be put into the default slot.

Provide.vue

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

const props = defineProps<{
  value: Record<string, any>
}>()

for (const [key, value] of Object.entries(props.value)) {
  provide(key, value)
}
</script>

<template>
  <slot name="default"/>
</template>

and use it like this:

<template>
  <provide value='toProvide'>
    <my-component v-bind='myProps' />
  </provide>
</template>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!