组件插槽可以便捷的设置组件内容。
<div id="app">
<com-a>
示例内容
<span>组件的主体内容</span>
</com-a>
</div>
单个插槽
如果我们希望组件标签可以像 HTML 标签一样设置内容,那么组件的使用灵活度会很高。
<div id="app">
<p>示例内容1</p>
<com-a>示例内容2</com-a>
</div>
但平常我们书写的组件,组件首尾标签中书写的内容会被抛弃。
<div id="app">
<com-a></com-a>
</div>
我们需要通过 <slot> 进行插槽设置。
Vue.component('ComA', {
tamplate: `
<div>
<h3>组件标题</h3>
<slot></slot>
</div>
`
})
<div id="app">
<com-a>
示例内容
<span>组件的主体内容</span>
</com-a>
</div>
需要注意模板内容的渲染位置:
<div id="app">
<com-a>
这里只能访问父组件的数据
{{ parValue }}
</com-a>
</div>
var ComA = {
template: `
<div>
<p>组件 A:</p>
<slot><slot>
</div>
`
}
new Vue({
el: '#app',
data: { parValue: '父组件数据' },
components: { ComA }
})
我们可以在 <slot> 中为插槽设置默认值,也称为后备内容。
<div id="app">
<com-a></com-a>
</div>
var ComA = {
template: `
<div>
<p>组件 A:</p>
<slot>这是默认文本<slot>
</div>
`,
data () {
return {
value: '子组件数量'
}
}
}
具名插槽
如果组件中有多个位置需要设置插槽,按需要给 <slot> 设置 name,称为具名插槽。不设置 name 的插槽为默认插槽。
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
在父组件中通过 template 占位符并设置 v-solt 对应同名插槽。并且 v-solt 只能在 template 中使用。
<com-a>
<template v-slot:header>
<h1>组件头部内容</h1>
</template>
<template v-slot:default>
<p>组件主体内容第一段</p>
<p>组件主体内容第二段</p>
</template>
<template v-slot:footer>
<p>组件底部内容</p>
</template>
</com-a>
默认插槽可以不设置 v-solt ,而其他具名插槽也可以通过 #
号简写 v-solt 。
<com-a>
<template #header>
<h1>组件头部内容</h1>
</template>
<p>组件主体内容第一段</p>
<p>组件主体内容第二段</p>
<template #footer>
<p>组件底部内容</p>
</template>
</com-a>
作用域插槽
作用域插槽用于让插槽可以使用子组件的数据。组件将需要被插槽使用的数据通过 v-bind 绑定给 <slot>,这种用于给插槽传递数据的属性称为插槽 prop。
var ComA = {
template: `
<div>
<p>组件 A:</p>
<slot :value="value">这是默认文本</slot>
</div>
`,
data () {
return {
value: '子组件数据'
}
}
}
组件绑定数据后,插槽中需要通过 v-slot 接收数据。
<div id="app">
<com-a>
<template v-slot:default="dataObj">
{{ dataObj.value }}
</template>
</com-a>
</div>
如果只存在默认插槽,同时又需要接收数据,可以进行简写:
<div id="app">
<com-a v-slot="dataObj">
{{ dataObj.value }}
</com-a>
</div>
还可以通过 ES6 的解构操作进行数据接收。
<div id="app">
<com-a v-slot:default="{ value }">
{{ value }}
</com-a>
</div>