为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发Vue.js
实现了一个内容分发 API
,使用特殊的 slot
元素作为原始内容的插槽。
在学习内容分发 API
之前,我们先明确内容在哪个作用域里编译。先看小栗子:
<!--父组件中的作用域-->
<div id="app" style="border:2px solid green;height:400px;">
<!-- v-show肯定是由父组件定义好的东西控制 -->
<my-acomponent v-show="chilshow">
<!-- 此处渲染出来的肯定是父组件中的message -->
{{message}}
</my-acomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
Vue.component('my-acomponent', {
// 子组件的作用域定义到此处
template: '<div v-show="chilshow">我是一个组件</div>',
data: function() {
return {
message: '我是子组件中的内容',
// 子组件中的
chilshow: true
}
},
})
var app = new Vue({
el: '#app',
data: {
message: '我是父组件中的内容',
// 父组件中的
chilshow: false
}
})
</script>
以上message
应该绑定到父组件的数据,还是绑定到子组件的数据?答案是父组件。组件作用
域简单地说是:
父组件的内容与子组件相混合,从而弥补了视图的不足
混合父组件的内容与子组件自己的模板
举个栗子:
单个插槽的用法:
<!--父组件中的作用域-->
<div id="app" style="border:2px solid green;height:400px;">
<my-acomponent>
<p>如果我存在,子组件slot中的内容就不会显示</p>
</my-acomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
Vue.component('my-acomponent', {
// 子组件的作用域定义到此处
template: '<div >\
<slot>\
如果父组件中没有插入内容, 我就作为默认内容出现 \
</slot>\
</div>',
})
var app = new Vue({
el: '#app',
data: {
message: '我是父组件中的内容',
}
})
</script>
顾名思义 是有具体名字的插槽:
看栗子:
<!--父组件中的作用域-->
<div id="app" style="border:2px solid green;height:400px;">
<my-acomponent>
<p>如果我存在,子组件slot中的内容就不会显示</p>
</my-acomponent>
<br>
<hr> 具名插槽:
<name-acomponent>
<h3 slot="header">我是标题</h3>
<p>我是正文内容</p>
<p>正文内容有两端</p>
<p slot="footer">我是底部内容</p>
</name-acomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
Vue.component('my-acomponent', {
// 子组件的作用域定义到此处
template: '<div >\
<slot>\
如果父组件中没有插入内容, 我就作为默认内容出现 \
</slot>\
</div>',
})
// 具名插槽的用法
Vue.component('name-acomponent', {
template: '<div>\
<div class="header">\n' +
' <slot name="header">\n' +
' \n' +
' </slot>\n' +
'</div>\n' +
'<div class="contatiner">\n' +
' <slot>\n' +
' \n' +
' </slot>\n' +
'</div>\n' +
'<div class="footer">\n' +
' <slot name="footer">\n' +
'\n' +
' </slot> \n' +
'</div>' +
' </div>'
})
var app = new Vue({
el: '#app',
data: {
message: '我是父组件中的内容',
}
})
</script>
作用域插槽是一种特殊的slot
,使用一个可以复用的模板来替换已经渲染的元素
——从子组件获取数据
====注意:template
模板是不会被渲染的
2.5.0版本之前的写法 在template
魔板中定义临时变量prop
用 prop.text
访问即可
2.5.0之后就会方便很多,不必再定义在template
魔板中,可以直接使用.
小栗子:
<div id="app" style="border:2px solid green;height:400px;">
<my-acomponent>
<!--2.5.0版本之前的写法 在template魔板中定义临时变量prop用 prop.text访问即可 -->
<template slot="abc" slot-scope="prop">
{{prop.text}}
</template>
<!-- 2.5.0版本之后就方便很多 -->
<p slot="abc" slot-scope="prop">
{{prop.text}} <br>{{prop.ss}}
</p>
</my-acomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
Vue.component('my-acomponent', {
// 子组件的作用域定义到此处 在slot中定义要传递的数据text
template: '<div >\
<slot text="我是来自子组件中的数据" name="abc" ss="2.5.0之后就会方便很多">\
\
</slot>\
</div>',
})
var app = new Vue({
el: '#app',
data: {
message: '我是父组件中的内容',
}
})
</script>
通过this.$slot(NAME)
访问
小栗子:
<!--父组件中的作用域-->
<div id="app" style="border:2px solid green;height:400px;">
<my-acomponent>
<p>如果我存在,子组件slot中的内容就不会显示</p>
</my-acomponent>
<br>
<hr> 具名插槽:
<name-acomponent>
<h3 slot="header">我是标题</h3>
<p>我是正文内容</p>
<p>正文内容有两端</p>
<p slot="footer">我是底部内容</p>
</name-acomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
Vue.component('my-acomponent', {
// 子组件的作用域定义到此处
template: '<div >\
<slot>\
如果父组件中没有插入内容, 我就作为默认内容出现 \
</slot>\
</div>',
})
// 具名插槽的用法
Vue.component('name-acomponent', {
template: '<div>\
<div class="header">\n' +
' <slot name="header">\n' +
' \n' +
' </slot>\n' +
'</div>\n' +
'<div class="contatiner">\n' +
' <slot>\n' +
' \n' +
' </slot>\n' +
'</div>\n' +
'<div class="footer">\n' +
' <slot name="footer">\n' +
'\n' +
' </slot> \n' +
'</div>' +
' </div>',
// 访问插槽
mounted: function() {
// 访问插槽
var header = this.$slots.header
console.log(header)
var text = header[0].elm.innerText
console.log(text)
var html = header[0].elm.innerHTML
console.log(html)
},
})
var app = new Vue({
el: '#app',
data: {
message: '我是父组件中的内容',
}
})
</script>
效果图:
效果图