はじめに
Vue.jsでは、バージョン2.6.0でv-slotディレクティブが導入されました。これは名前付きスロットとスコープ付きスロットを統一的に扱うことのできるディレクティブなのですが、ドキュメントを読んだときに少しこんがらかったので頭の中を整理することを兼ねて投稿します。
v-slotディレクティブ
v-slotディレクティブの書き方は以下のとおりです。
v-slot:{スロット名} = "{子コンポーネントからのデータを受け取る変数}"
これを親コンポーネントのテンプレート内のカスタムタグに記述します。名前付きコンポーネントのみを使うときはイコール以降は不要です。
具体例
以下に具体例を示します。
main.htmlでは、名前、スコープ付きのスロット(ヘッダー)、名前付きスロット(フッター)を指定しています。
ヘッダーに関しては、子コンポーネントからmessageを受け取っていることが分かります。
名前、スコープ付きのスロットでは、v-slotを以下のように書いています。ここでは、headerがスロット名、slotPropsが子コンポーネントからのデータを受け取る変数です。
v-slot:header="slotProps"
slotPropsには以下のようなオブジェクトが格納されます。オブジェクトのプロパティ名(ここでは"message")は、v-bind:messageのmessageです。すなわち、v-bind:{オブジェクトのプロパティ名}となります。
{ "message": "hello from child!" }
main.html
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta charset='UTF-8'>
</head>
<body>
<div id="app">
<child-component>
<template v-slot:header="slotProps">
<p>{{ slotProps.message }}</p>
</template>
<template v-slot:footer>
<p>FOOTER</p>
</template>
</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>
main.js
const ChildComponent = {
template: `
<div>
<header>
<slot name="header" :message="message">DEFAULT HEADER CONTENTS</slot>
</header>
<footer>
<slot name="footer">DEFAULT FOOTER CONTENTS</slot>
</footer>
</div>
`,
data(){
return {
message: "hello from child!"
}
}
}
const app = new Vue({
el: "#app",
components: {
ChildComponent
}
})
実行結果
hello from child!
FOOTER