【Nuxt3】slotを使ってコンポーネントの用途を広げる

シェアする:

この記事をおすすめしたい人

  • コンポーネントの内側にHTMLを書きたいと思っている人
  • Nuxt3のslotに「ん?」ってなった人
  • つまりオレ

Nuxt v3の調査、slot編です。

いや、これ、Nuxt3に移植した際に公式コンポーネントでこんな↓コードを見てですね。


<template>
  <div>
    <header>header</header>
    <slot />
    <footer>footer</footer>
  </div>
</template>

このコンポーネント名を「TestComponent」だとすると、


<TestComponent>
ここに中身が書けるんじゃね?
それが<slot />で展開されるんじゃね?
</TestComponent>

となったわけなんです。

これじゃ意味不明な人もいると思うので、具体的にやりたいことも含めて実験していこうと思います。

やりたいこと

やりたいこととしては、例えば呼び出しが側がこんな↓コンポーネント。


<TestComponent title="ここにタイトルが入る">
<p>
ここに本文が入る。
</p>
</TestComponent>

で、TestComponentの中身はこんな↓風に書きたい。


<section>
<h2>{{title}}</h2>
<nakami />
</section>

これでこんな↓感じにHTMLが出力される。


<section>
<h2>ここにタイトルが入る</h2>
<p>
ここに本文が入る。
</p>
</section>

こういうことがやりたいんですよ。

h2を含むセクションをクラス名とか構造(h2の内側にspanがあるとか)を流用したくて、上のようなコンポーネントを作りたいなと思うことがあったんです。

いや、けっこう毎回かも。

で、上でnakamiになっている部分をpropsで受け取ったりとか試してはいたんですが、まぁ書きづらい。 しかも、タグを含む場合はv-htmlでどうにかなりますが、コンポーネントを含む場合が非常に面倒で、v-runtime-templateを使わないといけない。

なんかうまい書き方はないかなーというのがスタート地点です。

Vue.jsのslotという機能を使う

僕が気付いたのはNuxt3のapp.vueについて調べていた時だったんですが、実はこれNuxt2の時代からあった機能みたいです。

小文字スタートなのでv2もいけそうかなと。

まずはコンポーネント側をこう↓実装して(propsにtitle)、


<section>
<h2>{{title}}</h2>
<slot />
</section>

呼び出し側をこんな↓風に書いてみました。


<TestComponent title="ここにタイトルが入る">
ここに本文が入る。
</TestComponent>

出力されたHTMLはこんな↓風になりました。


<section>
<h2>ここにタイトルが入る</h2>
<!--[-->
ここに本文が入る。
<!--]-->
</section>

思った通りに動いとるやないか…。

もっと早く知りたかったです。

HTMLタグはちゃんと展開されるのか?

内側に置いたHTMLタグがちゃんと展開されるのかのテストとして、次の4つをテストしました。

  • div
  • p
  • ul
  • img

コードはこんな↓感じです。


<TestComponent title="ここはtitleのテストだよー">
<div>ここはdivのテストだよー</div>
<p>ここはpのテストだよー</p>
<ul>
<li>ここはulのテストだよー</li>
</ul>
<img src="/favicon.ico">
</TestComponent>

全部正常に動くやないか…。

もっと早く知りたかったです。

v-bindで変数込みでやったりしてみましたが、問題なかったです。

他にトラブりそうなパターンあるかな?

コンポーネントの展開はできるのか

デフォルトのコンポーネントの展開

まずはNuxt側が持っているコンポーネントとしてNuxtLinkを試してみます。

こんな↓風に呼び出し側を書いてみると、


<TestComponent>
<NuxtLink to="/test/">リンクのテスト</NuxtLink>
</TestComponent>

出力されたHTMLはこう↓。


<section>
<a href="/test/" class="">リンクのテスト</a>
</section>

いけますね。

自作コンポーネントの展開

自作コンポーネントの展開も試します。 テスト用にMyComponentとしてこんな↓コンポーネントを用意しました。


<template>
<span>ここがMyComponentの領域</span>
</template>

こんな↓風に呼び出し側を書いてみると、


<TestComponent>
<MyComponent />
</TestComponent>

出力されたHTMLはこう↓。


<section>
<span>ここがMyComponentの領域</span>
</section>

これもいけますね。

あんまり細かくチェックは出来てないですが、たぶんコレ、なんでもいけるんじゃないですかね。

固有のケースでおかしなことになりそうだったらまた追記しておきます。

まとめ

今回はNuxt3で初めて気付いたけど実はv2の頃からあったslotという機能についてテストしてみました。

感想としては、

もっと早く教えとかんかいや!

となりました。 たぶん既存プロジェクトもいろいろ書き換わりそう。

はぁ…。

以上、WordPressからお届けしました!

シェアする: