Vue: Functional component not rendering named slot (following #8871)

Created on 1 Oct 2018  路  7Comments  路  Source: vuejs/vue

Version

2.5.17

Reproduction link

https://codesandbox.io/s/p9mx85qpz0

Steps to reproduce

nothing in particular.

What is expected?

It should display Hello World

What is actually happening?

It displays Hello


Following https://github.com/vuejs/vue/issues/8871 I made App.vue non-functional:

If you make Child.vue non-functional it works: https://codesandbox.io/s/pw5lzx2w90

If you use default (not named) slots it works: https://codesandbox.io/s/04jrp3y4ln

has workaround

Most helpful comment

Responded on the Vue Forum as well, is this maybe the same issue as in #7587?

It works by using a scoped slot:
https://codesandbox.io/s/0p96w8o1pw

All 7 comments

Responded on the Vue Forum as well, is this maybe the same issue as in #7587?

It works by using a scoped slot:
https://codesandbox.io/s/0p96w8o1pw

I've been running into this for a little while now, trying to make a simple functional component to use with values created by daggy.js.

I've created a codesandbox thingy with a number of cases showing the effects of this.

Peeking at the VNodes being created during the render call, the issue seems to be caused by the root element of a named unscoped slot passed to a functional component still having data.slot on its VNode when that VNode is returned by the functional component.

Example results of using a named, unscoped slot with a plain DOM node:

Render Template:
  transition[name=overlay-fade]
    my-functional-component
      div.busy-overlay[slot=waiting]
        spinner

VNode: transition[name=overlay-fade]
  tag: 'vue-component-19-transition'
  children: undefined
  componentOptions:
    tag: 'transition'
    children: [
      VNode: div.busy-overlay[slot=waiting]
        tag: 'div'
        data:
          slot: 'waiting'
        children: [
          VNode: spinner
            tag: 'vue-component-25-spinner'
            children: undefined
            componentOptions:
              tag: 'spinner'
        ]
    ]

Compare this to the use of a template tag as the slot root:

Render Template:
  transition[name=overlay-fade]
    my-functional-component
      template[slot=waiting]
        div.busy-overlay
          spinner

VNode: transition[name=overlay-fade]
  tag: 'vue-component-19-transition'
  children: undefined
  componentOptions:
    tag: 'transition'
    children: [
      VNode: div.busy-overlay
        tag: 'div'
        data:
          slot: (not present)
        children: [
          VNode: spinner
            tag: 'vue-component-25-spinner'
            children: undefined
            componentOptions:
              tag: 'spinner'
        ]
    ]

The exact component used to wrap the functional component doesn't matter, as demonstrated in the codesandbox example at the top of this post, I just ran into this using the Transition component most recently, hence the appearance of transition in the outlines above.

For now, I'm going to stick to wrapping the contents of slots in <template>s. I may also add a wrapper function for getting normalized slot contents in functional components.

I've ran into this issue too. Seems to only occur when a functional component wraps another functional component.

I have same problem, When a functional component wraps another functional component.

there should be an anwser you want here

7587

there should be an anwser you want here

7587

Ok, can be a solution , but I use SFC functional with default slot:

<template functional>
</template>

In this specific scenario, the Parent component should be written like this:

  render(h, context) {
    context.data.scopedSlots = {
      username: () => h('span', {}, 'World')
    }
    return h(Child, context.data, [])
  },

I think we may need to adapt the functional component to allow passing a child with a slot attribute:

  render(h, context) {
    context.data.scopedSlots = {
      username: () => h('span', {}, 'World')
    }
    return h(Child, context.data, [
      h('span', { slot: 'username' }, 'World')
    ])
  },

@nickmessing I imagine the jsx plugin transforms into this because it has no way of knowing if Child is functional or not

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gkiely picture gkiely  路  3Comments

loki0609 picture loki0609  路  3Comments

aviggngyv picture aviggngyv  路  3Comments

paceband picture paceband  路  3Comments

hiendv picture hiendv  路  3Comments