ワラベンチャー
コーディング・スタイルだぜ! の部
スロットの書き方を決めておこうぜの章だぜ!

きふわらべのお父ん
じゃあ、まず、スロットって何かの説明からするか。

きふわらべのお父ん
👇 こういうデータが載ってる本を作りたいとするだろ。
expected:
名前: すっぽん
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。

きふわらべのお父ん
👇 Vue3 では HTML をこんな感じに書くかな。
📄 a child .vue file:
<template> <div style="background-color: skyblue;"> 名前: すっぽん<br/> 体力: 100<br/> 魔力: 50<br/> 紹介文: 私は勇者です。よろしくお願いします。<br/> <v-img src="https://picsum.photos/64/64" alt="なんか画像" style="width: 64px; height: 64px;" /> </div> </template>

きふわらべのお父ん
ひとまず、以下の黄緑色の部分を穴埋めの穴にしたいと思ってくれだぜ。
名前: ここを穴にしたい
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。

きふわらべのお父ん
👇 じゃあ、HTML では以下の黄緑色の部分のように、{{ ハンドルバー }} を使うかな。
📄 a child .vue file:
<template>
<div style="background-color: skyblue;">
名前: {{ name }}<br/>
体力: 100<br/>
魔力: 50<br/>
紹介文: 私は勇者です。よろしくお願いします。<br/>
<v-img
src="https://picsum.photos/64/64"
alt="なんか画像"
style="width: 64px; height: 64px;"
/>
</div>
</template>

ひよこ
name 変数は、説明すると横道に逸れるから省略ねえ。

きふわらべのお父ん
では、以下のような、テキストとか画像とかもある部分を穴埋めの穴にしたいと思ったときどうするかだぜ。
名前: すっぽん
体力: 100
魔力: 50
紹介文: ここらへんを
穴にしたい
体力: 100
魔力: 50
紹介文: ここらへんを
穴にしたい

きふわらべのお父ん
👇 そんなとき、スロットを使ってこう書くんだぜ。
📄 no-1-child.vue:
<template>
<div style="background-color: skyblue;">
名前: すっぽん<br/>
体力: 100<br/>
魔力: 50<br/>
紹介文: <slot></slot><br/>
</div>
</template>

ひよこ
要は HTML をぶっこめる穴よねえ。

きふわらべのお父ん
で、この作ったテンプレートは、他のテンプレートから呼び出せるんだぜ。
呼び出される方を子、呼び出す方を親とするとき、
👇 親の方で以下のように書けば……。
呼び出される方を子、呼び出す方を親とするとき、
👇 親の方で以下のように書けば……。
📄 a parent .vue file:
<template> <no-1-child> わたしはオークです。よろしくねえ。 <v-img src="https://picsum.photos/64/64" alt="なんか画像" style="width: 64px; height: 64px;" /> </no-1-child> </template> <script setup lang="ts"> import No1Child from '@/components/no-1-child.vue'; </script>

ひよこ
👆 No1Child は、タグ名にするとき kebab-case にできるのよね。"<No1Child>" とも書けるし、 "<no-1-child>" とも書ける。
名前: すっぽん
体力: 100
魔力: 50
紹介文: わたしはオークです。よろしくねえ。
体力: 100
魔力: 50
紹介文: わたしはオークです。よろしくねえ。

きふわらべ
以下のように、スロットを2か所作りたいときはどうするんだぜ?
名前: すっぽん
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。
制作者近影: 大好物はラーメン。
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。
制作者近影: 大好物はラーメン。

きふわらべのお父ん
👇 例えば、次のように書けるぜ。
📄 no-1-2-child.vue:
<template> <div style="background-color: skyblue;"> 名前: すっぽん<br/> 体力: 100<br/> 魔力: 50<br/> 紹介文: <slot></slot><br/> 制作者近影: <slot name="author"></slot><br/> </div> </template>
📄 a parent vue file:
<template> <no-2-child> わたしはオークです。よろしくねえ。 <v-img src="https://picsum.photos/64/64" alt="なんか画像" style="width: 64px; height: 64px;" /> <template #author> 大好物はラーメン。<br/> <v-img src="https://picsum.photos/64/64" alt="なんか画像" style="width: 64px; height: 64px;" /> </template> </no-2-child> </template> <script setup lang="ts"> import No2Child from '@/components/no-2-child.vue'; </script>

きふわらべのお父ん
👇 するとこうなる。
actual:
名前: すっぽん
体力: 100
魔力: 50
紹介文: わたしはオークです。よろしくねえ。
制作者近影: 大好物はラーメン。
体力: 100
魔力: 50
紹介文: わたしはオークです。よろしくねえ。
制作者近影: 大好物はラーメン。

ひよこ
👆 Visual Studio Code (略称:VSCode)を使ってると、以下のようなエラーメッセージが出るんだけど?

Property 'author' does not exist on type '{}'. ts-plugin(2339) [Ln 349, Col 28]

きふわらべのお父ん
VSCode の Vue公式エクステンションの不具合なんじゃないかな。
Grok に聞いたら、なんかあれしろ、これしろというのでやっては動かず、
聞き返しては次にあれしろというからやってみたが動かず、というのを4回ぐらいやったが、解決しなかったぜ。
Grok に聞いたら、なんかあれしろ、これしろというのでやっては動かず、
聞き返しては次にあれしろというからやってみたが動かず、というのを4回ぐらいやったが、解決しなかったぜ。

きふわらべ
Grok は知ったかだからな。

ひよこ
問題の切り分けをしましょう。
Tauri + Vue3 の環境でエラーが出るんだけど、
Nuxt + Vue3 の環境ではこのエラーは出ないわよ?
Tauri + Vue3 の環境でエラーが出るんだけど、
Nuxt + Vue3 の環境ではこのエラーは出ないわよ?

きふわらべのお父ん
えっ、じゃあ Tauri 側の不具合かだぜ?
tauri-cli のバージョンは 2.0.4、
今は 2.8.x まで出てるらしいんで、アップデートしてみるか……
tauri-cli のバージョンは 2.0.4、
今は 2.8.x まで出てるらしいんで、アップデートしてみるか……
pnpm add -D @tauri-apps/cli@latest

きふわらべのお父ん
あれっ、 @tauri-apps/cli が 2.8.3 から 2.8.4 に更新されて、
tauri-cli のバージョンは 2.0.4 のままだ……、どういうこっちゃ。
tauri-cli のバージョンは 2.0.4 のままだ……、どういうこっちゃ。

きふわらべ
Tauri とか 2020年に出てきた技術だからな。
まだまだ不具合が多いんじゃないか?
まだまだ不具合が多いんじゃないか?

ひよこ
べつに Vue3 専用のフレームワークでもないですしね

きふわらべのお父ん
じゃあ、VSCode の PROBLEMS ペーンが ❌ 印でまっかっかでも気にしないでおくか……。
利用人口が増えたら誰かが不具合を直してくれるだろ……
利用人口が増えたら誰かが不具合を直してくれるだろ……

きふわらべ
VSCode の PROBLEMS にメッセージが多くてうざいというだけなら、
ターミナルのフィルター欄に以下のようにかけば、該当するメッセージを非表示にできるぜ。
ターミナルのフィルター欄に以下のようにかけば、該当するメッセージを非表示にできるぜ。
!Property '*' does not exist on type '{}'.

きふわらべのお父ん
あっ、こんなんできるんだ、じゃあ、これでしのごう。
保存はできないのか。毎回入れるか……めんどくさ。
保存はできないのか。毎回入れるか……めんどくさ。
スロット・プロパティ

きふわらべのお父ん
次は話が変わって、子コンポーネントから親コンポーネントへ、逆向きに値を渡す方法を説明するぜ。

きふわらべのお父ん
👇 こういうデータが載ってる本を作りたいとするだろ。
expected:
名前: すっぽん
ヒットポイント: 100
マジックパワー: 50
ヒットポイント: 100
マジックパワー: 50

きふわらべのお父ん
👇 で、子コンポーネントの方には、ヒットポイントとか、マジックパワーといった見出しは持っていないものとするぜ。
📄 no-1-3-child.vue:
<template> <div style="background-color: skyblue;"> 名前: すっぽん<br/> <slot name="hp" :hit-point="100"></slot><br/> <slot name="mp" :magic-power="50"></slot><br/> </div> </template> <script setup lang="ts"> const slots = defineSlots<{ default(): any; hp(props: { hitPoint: number }): any; mp(props: { magicPower: number }): any; }>(); </script>

きふわらべのお父ん
👇 そこで、親コンポーネントの方で見出しを用意して、子コンポーネントから値を受け取るように書くぜ。
📄 a parent .vue file:
<template> <no-1o3o0-child> <v-slot #hp="slotProps"> ヒットポイント: {{ slotProps.hitPoint }} </v-slot> <v-slot #mp="slotProps"> マジックパワー: {{ slotProps.magicPower }} </v-slot> </no-1o3o0-child> </template> <script setup lang="ts"> import No1Child from '@/components/no-1-child.vue'; </script>
actual:
名前: すっぽん
ヒットポイント: 100
マジックパワー: 50
ヒットポイント: 100
マジックパワー: 50

きふわらべのお父ん
👆 できてるだろ。
ソースコード
ソースコードはこちら(^▽^)!