Categories
Vue 3

Vue 3 — Slots

Spread the love

Vue 3 is in beta and it’s subject to change.

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to use slots to populate content with Vue 3.

Slots

We can add slots to let us distribute content to the location we want.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <click-button>click me</click-button>
    </div>
    <script>
      const app = Vue.createApp({});

      app.component("click-button", {
        template: `
          <button>
            <slot></slot>
          </button>`
      });

      app.mount("#app");
    </script>
  </body>
</html>

We created the click-button component with a slot inside so that we can add our own content between the tags.

It’ll render to the button with ‘click me’ as the content text.

We can also add HTML between the tags.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <click-button><b>click me</b></click-button>
    </div>
    <script>
      const app = Vue.createApp({});

      app.component("click-button", {
        template: `
          <button>
            <slot></slot>
          </button>`
      });

      app.mount("#app");
    </script>
  </body>
</html>

We have the ‘click me’ text in bold since we have the b tag.

Other components can also be between the tags.

So we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <click-button><hello-world></hello-world></click-button>
    </div>
    <script>
      const app = Vue.createApp({});

      app.component("click-button", {
        template: `
          <button>
            <slot></slot>
          </button>`
      });

      app.component("hello-world", {
        template: `
          <b>click me</b>
        `
      });

      app.mount("#app");
    </script>
  </body>
</html>

We have the hello-world component in between the click-button tags and we’ll see the same result as before.

If a component’s template didn’t contain the slot element, then any content in between the tags would be discarded.

So if we have:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <click-button>click me</click-button>
    </div>
    <script>
      const app = Vue.createApp({});

      app.component("click-button", {
        template: `
          <button></button>
        `
      });

      app.mount("#app");
    </script>
  </body>
</html>

Then ‘click me’ wouldn’t be displayed and we have an empty button.

Render Scope

We can access items from the child component from the parent if we have a slot.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <click-button>
        delete {{item.name}}
      </click-button>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            item: {
              name: "this"
            }
          };
        }
      });

      app.component("click-button", {
        template: `
          <button>
            <slot></slot>
          </button>
        `
      });

      app.mount("#app");
    </script>
  </body>
</html>

Then we passed in the item.name string as the part of the content of the slot in the click-button component.

This is only for display. item is still in the parent’s scope.

Fallback Content

Fallback content can be added to a slot.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <click-button> </click-button>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            item: {
              name: "this"
            }
          };
        }
      });

      app.component("click-button", {
        template: `
          <button>
            <slot>submit</slot>
          </button>
        `
      });

      app.mount("#app");
    </script>
  </body>
</html>

to add default content between the slots.

Since we have nothing between the click-button tags, we’ll see ‘submit’ displayed.

Conclusion

Slots are useful for letting us distribute content within a component.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *