Home > Mobile >  Vuejs3 pass props to slots
Vuejs3 pass props to slots

Time:08-16

I have a problem I'm stuck on right now, which has been bothering me for a few days right now, but I couldn't find a reasonable solution. I'm not even sure if it's possible at all.

What exactly I have in mind: I want to pass properties via to the child components. However, I want to do this without specifying the scope in the parent, like this:

<MyComponent v-slot="foobar">
  <MySub :text="foobar.text" />
  <MySub :text="foobar.text" />
  <MySub :text="foobar.text" />
</MyComponent>

Since these components always occur together, so i would like to make the code cleaner for useability reasons. What I have tried (This is not meant to be working code, but just to illustrate what I want to achieve): Playground Sample

I also tried hacks like:

this.$slots.default().forEach((x) => {x.props.text = 'newText'})

But this seems to be most worst hack i could use (if it still would work :D ).

Hope somebody can help me. Codesamples in Playground:

The "normal" working way

What i want to achieve

CodePudding user response:

Seem like the kind of thing that could be solved with provide/inject

docs: https://vuejs.org/guide/components/provide-inject.html

example:

MyComponent.vue

<script>
  export default {
    data() {
      return {
        greetingMessage: 'hallo Test'
      }
    },
    provide(){
      return {greetingMessage: this.greetingMessage}
    }
  }
</script>

<template v-slot="foobar">
  <div>
    <slot :text="greetingMessage"></slot>
  </div>
</template>

MySub.vue

<script>
  import {inject} from "vue"
  export default {
    inject: ['greetingMessage'],
  }
</script>

<template :text="foobar.text">
  <div>
    {{ greetingMessage }}
  </div>
</template>

This will make the value defined in provide available to any child (no matter how deep) through inject.

However not that the provide does not include reactivity out-of-the-box, so if you are expecting that to be reactive, just wrap in a computed (using composition api)

MyComponent.vue

<script>
  import {computed} from "vue"
  export default {
    data() {
      return {
        greetingMessage: 'hallo Test'
      }
    },
    provide(){
      return {greetingMessage: computed(()=>this.greetingMessage)}
    }
  }
</script>

<template v-slot="foobar">
  <div>
    <slot :text="greetingMessage"></slot>
    <button @click="greetingMessage = greetingMessage '!'">
      change message
    </button>
  </div>
</template>

link to working example on sfc

  • Related