パーソンリンク アドベントカレンダー5日目です!🎉
環境
Vue.js2系
きっかけ
slotする親からVueコンポーネントに情報伝達がしたいケースがありました。
slotする内容でなければemitすれば良いだけの話ですが、このケースはそうはいきません。
具体的にいうと、slotしたDOM内のbutton要素がクリックされた時、
子コンポーネントのイベントを引数を渡して発火させたかったのです。
親コンポーネント
<sample-component>
<form>
<input type="text" id="keyword>
<button v-on:click="clickEvent(data)">実行</button>
</form>
</sample-component>
子コンポーネント
<slot v-bind:on="slotOn"></slot>
function slotOn(data) {
// dataを受け取り何らかの処理
}
対処結果
この場合は、scoped slotとactivatorを使います。
親コンポーネント
<sample-component>
<template v-slot:activator="{ on }">
<form>
<input type="text" id="keyword>
<button v-on:click="clickEvent(on)">実行</button>
</form>
</template>
</sample-component>
function clickEvent(on) {
return on(data);
}
子コンポーネント
<slot name="activator" v-bind:on="slotOn"></slot>
function slotOn(data) {
// dataを受け取り何らかの処理
}
こうすることで、slotの内容で発火するイベントから、子コンポーネント内の slotOn
関数を発火させ、尚且つ引数も渡すことができます。
解説
activator
v-slot:activator
は名前付きスロットの書き方です。
activator
という名前のスロットを作成しています。
ではv-slot:activator="{ on }"
は何をしているのでしょうか。
これは、スロットactivator
からon
というプロパティを取得して、
プロパティon
をon
という変数名に代入しています(分割代入)。
そしてon
の中身は、この例で言うと子コンポーネントで指定したslotOnメソッドになります。
function slotOn(data) {
// dataを受け取り何らかの処理
}
Scoped Slot
これらの機能を実現するのがVueのScoped Slot(スコープ付きスロット)です。
親コンポーネント内でスロットコンテンツとして子コンポーネントからプロパティを使えるようにするには、
slot
要素の属性に使いたいプロパティをバインドします。
<slot name="activator" v-bind:on="slotOn"></slot>
slot
要素にバインドされた属性はスロットプロパティと呼ばります。
親スコープ内でv-slot
の値として名前を指定することで、スロットプロパティを受け取ることができます。