Vue Slots
Vue:2.5
Slot
是一種 內容分配(Content Distribution)
的元件。通常在實務使用上,元件應用錯綜複雜,元件包著元件使用是常見的問題,而 Slot
就像一種插槽,可以將你想要的內容直接嵌入預留的空間。
基本使用
在使用 Slot
之前,要先瞭解 編譯作用域(Compilation Scope)
,不然很容易搞錯變數。
就先以一個簡單的範例熟悉一下 Slot
操作。
以下範例為製作 say
和 hello
元件,say
傳入 hello
元件,而 hello
則是傳入 vm.name
。
範例
<div id="app">
<!-- 傳入 hello 元件-->
<say>
<!-- 在這個階段,都是使用 Vue-Model 的變數(傳入 vm.name) -->
<hello>{{ name }}</hello>
</say>
</div>
Vue.component('say', {
template: `
<div class="say">
<h1>Say Component</h1>
<!-- Slot 預留空間,可以傳入語言元件 -->
<slot></slot>
</div>
`
});
Vue.component('hello', {
template: `
<div class="hello">
<h3>Hello Component</h3>
<p>
<!-- Slot 預留空間,可以傳入人名 -->
Hello,<slot></slot>
</p>
</div>
`
});
const vm = new Vue({
el: '#app',
data: {
name: 'Johnson Lu',
}
});
實際看產出的 HTML 應該可以比較好理解:
<div id="app">
<div class="say">
<h1>Say Component</h1>
<!-- 原本的 say.slot 被填入 hello 元件 -->
<div class="hello">
<h3>Hello Component</h3>
<!-- 原本的 hello.slot 被填入人名 -->
<p>Hello,Johnson Lu</p>
</div>
</div>
</div>
既然是插槽,當沒有傳入任何東西時,可以指定預設值。
範例
<div id="app">
<say></say>
</div>
Vue.component('say', {
template: `
<div class="say">
<h1>Say Component</h1>
<!-- Slot 預留空間 -->
<slot>我無話可說</slot>
</div>
`
});
Named Slots
上面提到的 Slot
例子,都是按照順序去填入,但如果自己不是元件的作者,在溝通上面就顯得困難。因此就要透過具名的 Slot
定義標準,讓大家知道怎麼把想要的資料填入 Slot
。
範例
<div id="app">
<mail>
<h4 slot="subject">You're fired</h4>
<p slot="content">
太不乖惹
</p>
</mail>
</div>
Vue.component('mail', {
template: `
<div class="mail">
<slot name="subject">信件標題</slot>
<slot name="content">
信件內容
</slot>
<slot name="footer">Best regards</slot>
</div>
`
});
const vm = new Vue({
el: '#app',
data: {}
});
Scoped Slots
最後,Slot
可以做大範圍的宣告和資料傳遞,方法很類似元件的 Props Down
,最常見的例子就是動態產生清單。
先看一個基本資料傳遞的範例:
<div id="app">
<hello>
<!-- 透過 <template> 宣告 slot name 及要使用 slot 的 data-->
<template slot="say" scope="props">
<span>{{ props.message }}</span>
</template>
</hello>
</div>
Vue.component('hello', {
data: function () {
return {
message: 'Hello JohnsonLu'
}
},
template: `
<div>
<!-- Slot 預設先 bind message -->
<slot name="say" :message="message"></slot>
</div>
`
});
我們要插入的 Slot
內容為 <span> Data </span>
,而其中 Data
是設定在 Component
的變數,因此需要透過宣告 scope="props"
將變數代出來使用。
動態產生清單的範例:
<div id="app">
<!-- Pass Props 給 component -->
<list :items="items">
<!-- 透過 template 宣告這是 Scoped Slots 的範圍,並且要使用 Props 的變數-->
<template slot="item" scope="props">
<!-- 使用 slot 的 text -->
<li>@{{ props.text }}</li>
</template>
</list>
</div>
Vue.component('list', {
props: ['items'],
template: `
<ul>
<!-- 用 v-for 爬出資料,並寫入 bind text -->
<slot name="item" v-for="item in items" :text="item.text"></slot>
</ul>
`
});
const vm = new Vue({
el: '#app',
data: {
items: [
{id: 1, text: 'Hello'},
{id: 2, text: 'Hey'},
{id: 3, text: 'Haha'}
]
}
});