Web component slot can be confusing

Web component spec writes about composition and slots. This spec is followed by Vue when they implement slots in Vue components. This might or might not be better than React flavor ...children, depending on your taste.

But passing content down several levels, each with multiple named slots, default slot, and each slot with default content can be pretty confusing. Let’s get it straight.

First we defined a few components. We have Grandparent, it will have some text and include a Parent, passing some contents to Parent. parent will have some text and include a Child, passing some contents to Child. Cool that makes sense.

So <slot> tag are wholes to be filled. If I have a <slot>, my parent component can pass things to fill there. Inside <slot> there are default contents. If nothing passed from above, default contents are shown. Named slots naturally have <slot name="xxx"> name attribute. The one without name attr is the default slot to dump everything.

If I’m a parent including a child component that has slots, I put a bunch of stuff in between the child component’s tags. I can give any tag an attribute slot. If not, slots will use default / empty. For default slot, all things inside child component’s tags, and are not within slot="xxx", will be dumped to default slot.

Hope this snippet clarifies:

<template>
  <div>
    <h1>grandparent</h1>
    <parent>
      <div slot="one">From grandparent to parent 1</div>
      <div slot="two">From grandparent to parent 2</div>
      <div slot="tri">From grandparent to parent 3</div>
    </parent>
  </div>
</template>

<script>
import Vue from '/Users/wang.boyang/.nvm/versions/node/v8.11.3/lib/node_modules/@vue/cli-service-global/node_modules/vue/dist/vue.esm.js';

const parent = Vue.component('parent', {
  template: `
  <div>
    <h1>parent</h1>
    <slot name="one">default content for parent one. If grandparent doesn't pass, this will show</slot>
    <slot name="two">default content for parent two. If grandparent doesn't pass, this will show</slot>
    <slot name="tri">default content for parent tri. If grandparent doesn't pass, this will show</slot>
  </div>
  `,
});

export default {
  name: 'grandparent',
  components: {
    parent
  }
};
</script>

To install needed cli pkgs:

npm install -g @vue/cli @vue/cli-service-global
Written on October 25, 2018