本文同步發表於Andy's Blog
在介紹slot之前,我們必須先瞭解一個觀念:編譯作用域
我們先來看個範例
codepen連結
<div id="app">
<div class="parent">{{msg}}</div>
<child>{{msg}}</child>
</div>
猜猜看,child
元件中是否會印出父層的msg:I'mparent
內容?
答案是不會的!原因是目前child所處的位置是父層作用域
,當然不會印出子層內容~
補充:在Vue生命週期中,Vue會在created階段時判斷是否有template
,如果有vue則會去編譯template內容,也因此,child元件不會顯示I'mparent內容
圖示結果:
1.父層作用域在父層編譯
2.子層作用域在子層編譯
若要突破作用域編譯問題,就要使用到slot
參考資料:Summer 夏天Vue.js: Slot
目的:突破作用域,將父層內容傳遞進來!通常會應用在如果內容不一定要放入component中時,可以透過slot傳遞一整個html結構進來。
Slot 是一種用於內容分配(Content Distribution / Transclusion)的元件,適用於複雜或巢狀元件的實作上,可以想像成是空間預留的方法,在迭代過程中再把內容塞進去。
卡斯伯老師在課堂上將slot分為三種:
1.沒有slot的狀態
<no-slot-component>
<p>這是一段沒有插槽使用的狀態</p>
</no-slot-component>
說明:即使寫p段落文字在子元件中,在html上依舊不會顯示。因為元件中的內容都會被模板替換掉。這就是上方提到作用域編譯的問題~
2.單組slot
特點:在模板中添加<slot><slot/>
HTML部分
<single-slot-component>
<p>使用這段取代原本的 Slot。</p>
</single-slot-component>
template部分
<script type="text/x-template" id="singleSlotComponent">
<div class="alert alert-warning">
<h6>我是一個元件</h6>
<slot>
如果沒有內容,則會顯示此段落。
</slot>
</div>
</script>
畫面上,就可以將<p>使用這段取代原本的 Slot。</p>
呈現在畫面上!如下
3.多組slot(具名插槽)
簡單來說,將內容放入指定位置
寫法:
1.在html加入slot
2.在元件模板插入 name
練習連結
HTML部分
<child>
<p>123</p>
<h1 class="header" slot="header">這是 HEADER</h1>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<p class="footer" slot="footer">這是 FOOTER</p>
</child>
<template id="child-template">
<div class="container">
<header>
<slot name="header">Default Header</slot>
</header>
<hr>
<main>
<slot>Default Body</slot>
</main>
<hr>
<footer>
<slot name="footer">Default Footer</slot>
</footer>
</div>
</template>
補充:html結構中若不想顯示標籤如a、header,可以使用
<template>
,這樣就不會顯示標籤摟~
猜猜看下面這個範例child元件
,會印出什麼內容?
練習連結
HTML部分
<div id="app">
<div class="parent">{{ msg }}</div>
<child>
<div>This "msg" is from parent: {{ msg }}</div>
</child>
</div>
<template id="child-template">
<div class="child">
<div>{{ msg }}</div>
<!-- 預設slot文字 -->
<slot> Default Slot Content </slot>
</div>
</template>
JavaSvript部分
// children component
Vue.component('child', {
template: '#child-template',
data: function () {
return {
msg: 'I\'m child.'
};
}
});
// parent component
var parent = new Vue({
el: '#app',
data: {
msg: 'I\'m parent.'
}
});
答案是:
原因:之所以child中的msg會印出I'm parent
字樣,就是因為child所在區域,還是在父層。因此編譯作用域還是在父層內。
在2.6.0中,我們為具名插槽和作用域插槽引入了一個新的統一的語法(即v-slot指令)。它取代了slot和slot-scope