Why Vue regular slots also available in this.$scopedSlots?

Viewed 3584

Please see this minimum example

Test.vue

<template>
  <div>
    <slot name="this_is_not_scoped_slots"/>
  </div>
</template>

<script >
import Vue from "vue";

export default Vue.extend({
  mounted() {
    console.log(Object.keys(this.$scopedSlots));
  }
});
</script>

App.vue

<template>
  <Test>
    <template #this_is_not_scoped_slots>But it shows in this.$scopedSlots</template>
  </Test>
</template>

<script>
import Test from "./Test.vue";

export default {
  components: {
    Test
  }
};
</script>

In the above example, this console will log out ["this_is_not_scoped_slots"].

Why is this happening?

There are two properties in Vue instance

  1. this.$slots
  2. this.$scopedSlots

These two act really differently:

  1. If you use v-slot:my_scope_name="{ someValue }", then my_scope_name won't show up in this.$slots
  2. However, no matter what you define, your named slots will always show up in this.$scopedSlots

Why is this happening?

I'm building a library, I want to conditional rendering if the user has provided named slots or not, should I always use this.$scopedSlots to detect those things?

1 Answers

According to the official API :

  1. ....
  2. All $slots are now also exposed on $scopedSlots as functions. If you work with render functions, it is now recommended to always access slots via $scopedSlots, whether they currently use a scope or not. This will not only make future refactors to add a scope simpler, but also ease your eventual migration to Vue 3, where all slots will be functions.
Related