懒得再写一遍,直接把我的笔记截图放上来了。
截图的内容其实是自己写的测试代码最后的效果,下面把测试代码贴出来:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 组件slot</title>
<script src="../js/vue.min.js"></script>
</head>
<body>
<div id="app1">
<p>开始Vue.js slot的学习</p>
<p>下面使用一个子组件component-a,在组件的模板(template)中设置slot</p>
<component-a>
<!-- <p>看这部分内容是不是会将组件中的slot的内容替换掉</p> -->
</component-a>
</div>
<p>----------------------------------------------</p>
<p>书上只讲了只有一个不具名的slot的例子,这里试一下多个不具名的slot会发生什么。</p>
<div id="app2">
<component-b>
<p>见证奇迹的时刻,多个不具名的slot的到底会怎样?</p>
</component-b>
</div>
<h4>在上面的例子中,我只写了一个“见证奇迹的时刻,多个不具名的slot的到底会怎样?”</h4>
<h4>但是在页面中显示了两行文字,因为在component-b组件的模板中定义了两个不具名的slot。</h4>
<h4>那么,结论就出来了,如果在组件中定义了多个不具名的slot,父组件会把所有没有指定slot属性的内容挨个插入组件中的slot里面去。所以,在实际应用中,还是最多只定义一个不具名的slot</h4>
<p>----------------------------------------------</p>
<h2>具名slot</h2>
<p>按照我的理解,具名slot的作用在于将不同的内容插入到不同的slot中去,最常见的例子是一个网页中,分为了头部、内容区域、脚部,各个部分应用不同的样式。</p>
<p>下面是一个具名slot的例子</p>
<div id="app3">
<component-c>
<div slot="footer">页面脚部</div>
<h3 slot='header'>标题</h3>
<p>这里是没有指定slot属性的正文部分</p>
<p slot="container">这是指定了slot的正文部分</p>
</component-c>
</div>
<h4>发现了一个小现象,就是不管在父组件中按什么顺序写,最终渲染在浏览器中的还是按子组件的顺序来</h4>
<p>----------------------------------------------</p>
<h2>作用域插槽</h2>
<p>作用域插槽是一种特殊的slot。怎么个特殊法呢?</p>
<h5>首先,它的写法特殊:</h5>
<p>在HTML代码中,在子组件中使用template标签,并且给template标签一个scope属性</p>
<h5>其次,它的作用特殊:</h5>
<p>它可以通过scope属性,获取子组件插槽中的数据</p>
<p>按我的理解,这个scope属性的值是一个对象,这个对象的属性就是子组件中slot的所有的属性</p>
<p>下面是例子:</p>
<div id="app4">
<p>这是component-d标签外的内容</p>
<component-d>
<p>这是template标签外的内容</p>
<template scope="props">
<p>这是template标签里面的内容,但是没有使用scope属性</p>
<p>下面的p标签只包含scope属性的内容</p>
<p>{{ props.msg }}</p>
</template>
</component-d>
</div>
<p>下面是另一个例子:列表组件</p>
<div id="app5">
<my-list :books="books">
<template slot="book" scope="books">
<li>{{ books.bookName }}</li>
</template>
</my-list>
</div>
<p>----------------------------------------------</p>
<script>
Vue.component('component-a',{
template:'<div><slot><div>如果父组件没有插入内容,我将作为默认出现</div></slot></div>'
});
Vue.component('component-b',{
template:'<div>\
<slot>\
<div>\
1)如果父组件没有插入内容,我将作为默认出现\
</div>\
</slot>\
<slot>\
<div>\
2)如果父组件没有插入内容,我将作为默认出现\
</div>\
</slot>\
</div>'
});
Vue.component('component-c',{
template:'<div>\
<slot name="header">\
<div>\
1)如果父组件没有插入内容,我将作为默认出现\
</div>\
</slot>\
<slot name="container">\
<div>\
2)如果父组件没有插入内容,我将作为默认出现\
</div>\
</slot>\
<slot>\
<div>\
4)如果父组件没有插入内容,我将作为默认出现(前面3个都是假的默认值,他们都有name属性)\
</div>\
</slot>\
<slot name="footer">\
<div>\
3)如果父组件没有插入内容,我将作为默认出现\
</div>\
</slot>\
</div>',
mounted:function(){
var header = this.$slots.header;
var main = this.$slots.container;
var footer = this.$slots.footer;
var sss = this.$slots.default;
console.log(sss);
console.log(footer[0].elm.innerHTML);
}
});
Vue.component('component-d',{
data:function(){
return {
msg:'子组件中的data中msg的内容'
}
},
template:'<div>\
<slot :msg="msg"></slot>\
</div>'
});
Vue.component('my-list',{
props:{
books:{
type:Array,
default:function(){
return [];
}
}
},
template:'\
<ul>\
<slot name="book" v-for="book in books" :book-name="book.name"></slot>\
</ul>'
});
var app1 = new Vue({
el:'#app1'
});
var app2 = new Vue({
el:'#app2'
});
var app3 = new Vue({
el:'#app3'
});
var app4 = new Vue({
el:'#app4'
});
var app5 = new Vue({
el:'#app5',
data:{
books:[
{name:'《Vue.js实战》'},
{name:'《JavaScript高级程序设计》'},
{name:'《Node.js实战》'},
{name:'《深入浅出Node.js》'}
]
}
});
</script>
</body>
</html>