為了讓元件可以組合,需要一種方式來混合父元件的內容與子元件自己的模板。這個過程被稱為 內容分發 (或 “transclusion” )。 Vue實作了一個內容分發 API,參考了目前 Web 元件規範草案,使用特殊的 <slot>
元素作為原始內容的插槽。本文將詳細介紹Vue內容分發slot
在深入內容分發 API 之前,先先明確內容在哪個作用域裡編譯。假定模板為
<child-component> {{ message }} </child-component>
message
應該綁定到父元件的數據,還是綁定到子元件的數據?答案是父元件。元件作用域簡單來說是:父元件模板的內容在父元件作用域內編譯;子元件模板的內容在子元件作用域內編譯。
一個常見錯誤是試圖在父元件範本內將一個指令綁定到子元件的屬性/方法:
<!-- 无效 --> <child-component v-show="someChildProperty"></child-component>
假定someChildProperty
是子元件的屬性,上例不會如預期般運作。父元件範本不應該知道子元件的狀態
如果要綁定作用域內的指令到一個元件的根節點,應當在元件自己的範本上做:
#Vue.component('child-component', { // 有效,因为是在正确的作用域内 template: '<p v-show="someChildProperty">Child</p>', data: function () { return { someChildProperty: true } } })
類似地,分發內容是在父作用域內編譯
一般地,如果子元件範本不包含<slot>
插口,父元件的內容將會被丟棄
var parentNode = { template: ` <p class="parent"> <p>父组件</p> <child> <p>测试内容</p> </child> </p> `, components: { 'child': childNode }, };
<p id="example"> <parent></parent></p><script src="https://unpkg.com/vue"></script><script>var childNode = { template: ` <p class="child"> <p>子组件</p> </p> `, };var parentNode = { template: ` <p class="parent"> <p>父组件</p> <child> <p>测试内容</p> </child> </p> `, components: { 'child': childNode }, };// 创建根实例new Vue({ el: '#example', components: { 'parent': parentNode } })</script>
如下圖所示, 測試內容
##
#匿名slot
當子元件範本只有一個沒有屬性的slot 時,父元件整個內容片段會插入到slot 所在的DOM 位置,並取代掉slot 標籤本身
var childNode = { template: ` <p class="child"> <p>子组件</p> <slot></slot> </p> `, };
var parentNode = { template: ` <p class="parent"> <p>父组件</p> <child> <p>测试内容</p> </child> </p> `, components: { 'child': childNode }, };
# 如果出現多於1個的匿名slot,vue將報錯
var childNode = { template: ` <p class="child"> <p>子组件</p> <slot></slot> <slot></slot> </p> `, };
【預設值】
最初在
<slot>標籤中的任何內容都被視為
備用內容,或稱為預設值。備用內容在子元件的作用域內編譯,並且只有在宿主元素為空,且沒有要插入的內容時才顯示備用內容
當slot存在預設值,且父元素在
var childNode = { template: ` <p class="child"> <p>子组件</p> <slot><p>我是默认值</p></slot> </p> `, }; var parentNode = { template: ` <p class="parent"> <p>父组件</p> <child></child> </p> `, components: { 'child': childNode }, };
# 當slot存在預設值,且父元素在< child>當中存在要插入的內容時,則顯示設定值
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">var childNode = {
template: ` <p class="child">
<p>子组件</p>
<slot><p>我是默认值</p></slot>
</p>
`,
};
var parentNode = {
template: ` <p class="parent">
<p>父组件</p>
<child>
<p>我是设置值</p>
</child>
</p>
`,
components: {
'child': childNode
},
};</pre><div class="contentsignin">登入後複製</div></div>
##
具名Slot
<slot>元素可以用一個特殊的屬性name
來設定如何分發內容。多個 slot 可以有不同的名字。具名slot 將符合內容片段中有對應slot 特性的元素
#
var childNode = { template: ` <p class="child"> <p>子组件</p> <slot name="my-header">头部默认值</slot> <slot name="my-body">主体默认值</slot> <slot name="my-footer">尾部默认值</slot> </p> `, };
var parentNode = { template: ` <p class="parent"> <p>父组件</p> <child> <p slot="my-header">我是头部</p> <p slot="my-footer">我是尾部</p> </child> </p> `, components: { 'child': childNode }, };
# 仍然可以有一個匿名slot,它是預設slot
,作為找不到匹配的內容片段的備用插槽。匿名slot只能作為沒有slot屬性的元素的插槽,有slot屬性的元素如果沒有配置slot,則會被拋棄###var childNode = { template: ` <p class="child"> <p>子组件</p> <slot name="my-body">主体默认值</slot> <slot></slot> </p> `, };
var parentNode = { template: ` <p class="parent"> <p>父组件</p> <child> <p slot="my-body">我是主体</p> <p>我是其他内容</p> <p slot="my-footer">我是尾部</p> </child> </p> `, components: { 'child': childNode }, };
插入 我是其他內容 被丟棄############## 如果沒有預設的slot,這些找不到符合的內容片段也會被拋棄######### 我是其他內容 都被拋棄############### #### 作用域插槽是一种特殊类型的插槽,用作使用一个 (能够传递数据到) 可重用模板替换已渲染元素。 在子组件中,只需将数据传递到插槽,就像将 props 传递给组件一样 在父级中,具有特殊属性 如果渲染以上结果,得到的输出是 【列表组件】 作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项 以上是Vue內容分發slot的詳細內容。更多資訊請關注PHP中文網其他相關文章!var childNode = {
template: ` <p class="child">
<p>子组件</p>
<slot name="my-body">主体默认值</slot>
</p>
`,
};
var parentNode = {
template: ` <p class="parent">
<p>父组件</p>
<child>
<p slot="my-body">我是主体</p>
<p>我是其他内容</p>
<p slot="my-footer">我是尾部</p>
</child>
</p>
`,
components: {
'child': childNode
},
};
作用域插槽
<p class="child">
<slot text="hello from child"></slot></p>
scope
的 <template>
元素必须存在,表示它是作用域插槽的模板。scope
的值对应一个临时变量名,此变量接收从子组件中传递的 props 对象var childNode = {
template: ` <p class="child">
<p>子组件</p>
<slot xxx="hello from child"></slot>
</p>
`,
};
var parentNode = {
template: ` <p class="parent">
<p>父组件</p>
<child>
<template scope="props">
<p>hello from parent</p>
<p>{{ props.xxx }}</p>
</template>
</child>
</p>
`,
components: {
'child': childNode
},
};
var childNode = {
template: ` <ul>
<slot name="item" v-for="item in items" :text="item.text">默认值</slot>
</ul>
`,
data(){
return{
items:[
{id:1,text:'第1段'},
{id:2,text:'第2段'},
{id:3,text:'第3段'},
]
}
}
};
var parentNode = {
template: ` <p class="parent">
<p>父组件</p>
<child>
<template slot="item" scope="props">
<li>{{ props.text }}</li>
</template>
</child>
</p>
`,
components: {
'child': childNode
},
};