この記事をおすすめしたい人
- コンポーネントの内側に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からお届けしました!
Nuxt.js v3の目次
- 第1回 インストール方法とかフォルダ構成の違いとか
- 第2回 nuxt.config.jsの書き方の違い
- 第3回 注意が必要そうなモジュール
- 第4回 コンポーネントのscriptの書き方がめっちゃ変わった
- 第5回 trailingSlashに手動で対応
- 第6回 injectの代用品を3つ紹介
- 第7回 v-forとv-ifの併用の代替案
- 第8回 defineNuxtComponentは救世主!
- 第9回 composablesがめっちゃ強いかもしれない
- 第10回 手動でAMPに対応する
- 第11回 フック一覧を簡単に調べた
- 第12回 axiosの代用品(useFetch、$fetch、useAsyncData)