Vue 插槽
插槽用于向組件傳遞內容,插槽內可以包含任何模板代碼,包括 HTML,甚至組件。如果 組件 沒有包含一個 <slot> 元素,則任何傳入它的內容都會被拋棄。
<slot-conponent>
Fluently
</slot-conponent>
Vue.component('slot-conponent', {
data() {
return {
}
},
template: `
<div>
Hello <slot></slot>
</div>
`
})
var app = new Vue({
el: '#app',
data: {}
})
<!-- 渲染為 -->
<div>
Hello Fluently
</div>
具名插槽
定義具體名稱的插槽,組件內的內容會根據名稱自動匹配到模板對應的地方。如果沒有匹配項,則顯示在默認插槽上,否則不顯示。
<!-- 具名插槽 -->
<slot-name>
<template slot="header">
<h1>header</h1>
</template>
<template slot="footer">
<h1>footer</h1>
</template>
<template slot="main">
<h1>main</h1>
</template>
<template><h1>默認插槽</h1></template>
</slot-name>
<!-- 具名插槽另一種寫法 -->
<slot-name>
<h1 slot="header">header</h1>
<h1 slot="footer">footer</h1>
<h1 slot="main">main</h1>
<h1>默認插槽</h1>
</slot-name>
Vue.component('slot-name', {
data() {
return {
}
},
template: `
<div>
<header>
<slot name="header"></slot>
</header>
<main>
<slot name="main"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
<!-- 默認插槽 -->
<div>
<slot></slot>
</div>
</div>
`
})
默認插槽
為插槽提供默認內容,同時允許覆蓋默認內容
<slot-default></slot-default>
<slot-default>Modify</slot-default>
Vue.component('slot-default', {
data() {
return {
}
},
template: `
<div>
<slot>Default</slot>
</div>
`
})
插槽編譯作用域
父組件模板的所有東西都會在父級作用域內編譯;子組件模板的所有東西都會在子級作用域內編譯。
<!-- 插槽編譯作用域 -->
<slot-scope>{{msg}}</slot-scope>
<!-- 訪問出錯,父級作用域模板不能訪問子級數據 -->
<slot-scope>{{childMsg}}</slot-scope>
Vue.component('slot-scope', {
data() {
return {
childMsg: 'childScope'
}
},
template: `
<div>
<slot>{{childMsg}}</slot>
</div>
`
})
var app = new Vue({
el: '#app',
data: {
msg: 'Scope'
}
})
作用域插槽
組件能夠從子組件獲取數據(slot-scope 特性從子組件獲取數據),根據數據去獨立渲染對應的表現
<todo-list v-bind:todos="todos">
<!-- 將 `slotProps` 定義為插槽作用域的名字 -->
<template slot-scope="slotProps">
<!-- 為待辦項自定義一個模板,-->
<!-- 通過 `slotProps` 定制每個待辦項。-->
<span v-if="slotProps.todo.isComplete">?</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
Vue.component('todo-list', {
props: ['todos'],
data() {
return {
}
},
template: `<ul>
<li v-for="todo in todos" v-bind:key="todo.id">
<slot v-bind:todo="todo">
<!-- 回退的內容 -->
{{ todo.text }}
</slot>
</li>
</ul>`
})
var app = new Vue({
el: '#app',
data: {
msg: 'Scope',
todos: [{
text: 'Java',
id: 1,
isComplete: false
}, {
text: 'JavaScript',
id: 2,
isComplete: true
}, {
text: 'Vue',
id: 3,
isComplete: true
}]
}
})
解構 slot-scope
下面兩種 template 具有相同的效果,通過解構 slot-scope 能夠使作用域插槽變得更干凈一些
<!-- 作用域插槽 -->
<todo-list v-bind:todos="todos">
<!-- 將 `slotProps` 定義為插槽作用域的名字 -->
<template slot-scope="slotProps">
<!-- 為待辦項自定義一個模板,-->
<!-- 通過 `slotProps` 定制每個待辦項。-->
<span v-if="slotProps.todo.isComplete">?</span>
{{ slotProps.todo.text }}
</template>
</todo-list>
<!-- 解構Slot -->
<todo-list v-bind:todos="todos">
<template slot-scope="{ todo }">
<span v-if="todo.isComplete">?</span>
{{ todo.text }}
</template>
</todo-list>