Subscribe on changes!

slots are now functions instead of arrays

avatar
Sep 4th 2020

Version

3.0.0-rc.10

Reproduction link

v2: https://codesandbox.io/s/new-silence-wx19w?file=/src/components/Provider.js

v3 https://codesandbox.io/s/eager-currying-uqj9y?file=/src/Provider.js

Steps to reproduce

Run this:

import { h } from 'vue';

export default {
  render() {
    return h('div', {}, this.$slots.default);
  },
};

and use it like <Provider> some content </Provider>

What is expected?

this.$slots.default renders the children

What is actually happening?

this.$slots.default() renders the children


I'm trying to make a library compatible with v2 & v3 at the same time, but I had a hard time finding out that slots now need to be called. In https://v3.vuejs.org/guide/migration/slots-unification.html#_3-x-syntax this doesn't seem to be mentioned

Workaround I found:

import { h } from "vue";

export default {
  render(localH) {
    return (h || localH)(
      "div",
      {},
      typeof this.$slots.default === "function"
        ? this.$slots.default()
        : this.$slots.default
    );
  }
};

Should this be documented or am I missing something? Thanks!

avatar
Sep 4th 2020

I see now, but it wasn't too straightforward since it wasn't mentioned in the "migration strategy" key. I'll make a pull request to add it a little more explicit, since I think I looked at least 30 minutes why it wasn't displaying anything :)

avatar
Sep 4th 2020

The migration guide, as it currently stands, assume you're migrating from 2.6+ vm.$scopedSlots instead of the soft-deprecated 2.x vm.$slots (see RFC and announcement).

vm.$scopedSlots entries are always functions and, since 2.6, all slots in vm.$slots are also present, as a function, in vm.$scopedSlots. Always returning a function has performance benefits, and the semantics are more similar to 3.x vm.$slots.

So, to be compatible with both 2.x and 3.x, a better approach is supporting this.$scopedSlots.header() in 2.x and this.$slots.header() in 3.x instead of this.$slots.header in 2.x and this.$slots.header() in 3.x.

avatar
Sep 4th 2020

Ah, that makes sense! I didn't migrate to the 2.6+ style in my project since I wanted to avoid breaking compatibility with older versions, but I guess it isn't the regular flow. Thanks for elaborating @leopiccionia