ワラベンチャー

コーディング・スタイルだぜ! の部

スロットの書き方を決めておこうぜの章だぜ!


きふわらべ2
きふわらべ
使っているウェブ・フレームワークは
Vue3
系列の Vuetify3 だぜ。
きふわらべのお父ん2
きふわらべのお父ん
じゃあ、まず、スロットって何かの説明からするか。
きふわらべのお父ん2
きふわらべのお父ん
👇 こういうデータが載ってる本を作りたいとするだろ。

expected:
名前: すっぽん
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。


きふわらべのお父ん2
きふわらべのお父ん
👇 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>
        


きふわらべのお父ん2
きふわらべのお父ん
ひとまず、以下の黄緑色の部分を穴埋めの穴にしたいと思ってくれだぜ。

名前: ここを穴にしたい
体力: 100
魔力: 50
紹介文: 私は勇者です。よろしくお願いします。


きふわらべのお父ん2
きふわらべのお父ん
👇 じゃあ、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>
        


ひよこ2
ひよこ
name 変数は、説明すると横道に逸れるから省略ねえ。
きふわらべのお父ん2
きふわらべのお父ん
では、以下のような、テキストとか画像とかもある部分を穴埋めの穴にしたいと思ったときどうするかだぜ。

名前: すっぽん
体力: 100
魔力: 50
紹介文: ここらへんを
穴にしたい


きふわらべのお父ん2
きふわらべのお父ん
👇 そんなとき、スロットを使ってこう書くんだぜ。

📄 no-1-child.vue:
<template>
    <div style="background-color: skyblue;">
        名前: すっぽん<br/>
        体力: 100<br/>
        魔力: 50<br/>
        紹介文: <slot></slot><br/>
    </div>
</template>
        


ひよこ2
ひよこ
要は HTML をぶっこめる穴よねえ。
きふわらべのお父ん2
きふわらべのお父ん
で、この作ったテンプレートは、他のテンプレートから呼び出せるんだぜ。

呼び出される方を子、呼び出す方を親とするとき、
👇 親の方で以下のように書けば……。

📄 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>
        


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


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

制作者近影: 大好物はラーメン。


きふわらべのお父ん2
きふわらべのお父ん
👇 例えば、次のように書けるぜ。

📄 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>
        


きふわらべのお父ん2
きふわらべのお父ん
👇 するとこうなる。

actual:
名前: すっぽん
体力: 100
魔力: 50
紹介文:  わたしはオークです。よろしくねえ。
制作者近影:  大好物はラーメン。



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

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


きふわらべのお父ん2
きふわらべのお父ん
VSCode の Vue公式エクステンションの不具合なんじゃないかな。

Grok に聞いたら、なんかあれしろ、これしろというのでやっては動かず、
聞き返しては次にあれしろというからやってみたが動かず、というのを4回ぐらいやったが、解決しなかったぜ。

きふわらべ2
きふわらべ
Grok は知ったかだからな。
ひよこ2
ひよこ
問題の切り分けをしましょう。

Tauri + Vue3 の環境でエラーが出るんだけど、
Nuxt + Vue3 の環境ではこのエラーは出ないわよ?
きふわらべのお父ん2
きふわらべのお父ん
えっ、じゃあ Tauri 側の不具合かだぜ?

tauri-cli のバージョンは 2.0.4、
今は 2.8.x まで出てるらしいんで、アップデートしてみるか……

pnpm add -D @tauri-apps/cli@latest
        


きふわらべのお父ん2
きふわらべのお父ん
あれっ、 @tauri-apps/cli が 2.8.3 から 2.8.4 に更新されて、
tauri-cli のバージョンは 2.0.4 のままだ……、どういうこっちゃ。
きふわらべ2
きふわらべ
Tauri とか 2020年に出てきた技術だからな。
まだまだ不具合が多いんじゃないか?
ひよこ2
ひよこ
べつに Vue3 専用のフレームワークでもないですしね
きふわらべのお父ん2
きふわらべのお父ん
じゃあ、VSCode の PROBLEMS ペーンが ❌ 印でまっかっかでも気にしないでおくか……。
利用人口が増えたら誰かが不具合を直してくれるだろ……
きふわらべ2
きふわらべ
VSCode の PROBLEMS にメッセージが多くてうざいというだけなら、
ターミナルのフィルター欄に以下のようにかけば、該当するメッセージを非表示にできるぜ。
!Property '*' does not exist on type '{}'.
        


きふわらべのお父ん2
きふわらべのお父ん
あっ、こんなんできるんだ、じゃあ、これでしのごう。
保存はできないのか。毎回入れるか……めんどくさ。

スロット・プロパティ


きふわらべのお父ん2
きふわらべのお父ん
次は話が変わって、子コンポーネントから親コンポーネントへ、逆向きに値を渡す方法を説明するぜ。
きふわらべのお父ん2
きふわらべのお父ん
👇 こういうデータが載ってる本を作りたいとするだろ。

expected:
名前: すっぽん
ヒットポイント: 100
マジックパワー: 50


きふわらべのお父ん2
きふわらべのお父ん
👇 で、子コンポーネントの方には、ヒットポイントとか、マジックパワーといった見出しは持っていないものとするぜ。

📄 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>
        


きふわらべのお父ん2
きふわらべのお父ん
👇 そこで、親コンポーネントの方で見出しを用意して、子コンポーネントから値を受け取るように書くぜ。

📄 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


きふわらべのお父ん2
きふわらべのお父ん
👆 できてるだろ。


ソースコード

ソースコードはこちら(^▽^)!