Slot内容分发
1、内容分发与编译作用域
在使用组件时,常常要像这样组合它们.
<app>
<my-com></my-com>
<my-com-2></my-com-2>
</app>
此时需要注意的是:
<app>
组件不知道它的挂载点会有什么内容。挂载点的内容是由<app>
的父组件决定的。<app>
组件很可能有它自己的模版。
此时很容易混乱,为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发
在此之前我们还需要知道编译作用域:
父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。
<my-com>
{{ message }}
</my-com>
这里的{{message}}取到的数据应该是父组件定义的数据(这里假设可以放数据),子组件my-com的数据在这里是拿不到的。
2、slot
slot是vue提供用来处理数据插槽或者说内容分发的工具。
2.1、匿名slot
以上实例中,这里的组件标签里面本来是不可以放置数据的,如果要放置数据,需要在组件的模板里面怎建一个标签,slot。
<div id="com">
<my-com>{{message}}</my-com>
</div>
<script>
var com_1={
template:"<div>大家好,我是Component </div>",
data(){
return{
name:"Jack"
}
},
methods:{
}
};
new Vue({
el:"#com",
data:{
message:'Hello'
},
components:{
'my-com':com_1
}
});
</script>
这里是无法拿到数据{{message}}的,因为没有开启插槽,我们需要在子组件的标签中怎建一个slot标签。
template:"<div>大家好,我是Component " +
"<slot></slot>" +
"</div>",
这是一个匿名slot,slot的位置就是父组价中数据插入的位置。
如果默认slot中有数据,而父组件中没有数据,那么显示默认slot中的数据,否则显示父组件中插入的数据
2.2、具名slot
除了匿名slot,当然还有具名slot啦。可以给slot一个name,然后在父组件中指定slot。
在存在匿名slot的情况下,不会默认展示具名slot的数据
<div id="com">
<my-com>
<p>是的哦</p>
<h2 slot="s1">有名字的插槽一</h2>
<p>是的呢</p>
</my-com>
</div>
<script>
var com_1={
template:"<div>大家好,我是Component" +
"<slot><p>{{name}}</p></slot>"+
"<h1><button>点击我{{name}}</button></h1>" +
"<slot name='s1'>插槽一</slot>"+
"</div>",
data(){
return{
name:"Jack"
}
}
};
new Vue({
el:"#com",
components:{
'my-com':com_1
}
});
</script>
注意:插槽的位置在哪里,数据就在那里显示
2.3、作用域插槽
这个解释比较复杂,可以说把子组件数据的作用域插到父组件中。
<div id="com">
<my-com>
<h2 slot="ss">数据。。。</h2>
<template scope="itemscope">
{{itemscope.about}}
</template>
</my-com>
</div>
<script>
var com_1={
template:"<div>{{name}}<br>" +
"<slot :about='about'>{{name}}</slot>" +
"<slot name='ss'></slot>" +
"</div>",
data() {
return {
name: "Jack",
about: 'About that !!!'
}
}
};
new Vue({
el:"#com",
components:{
'my-com':com_1
}
});
</script>
此时在父组件的template下就可以拿到子组件的数据啦。
3、内容分发
这就是一个内容分发的实例,在上篇组件数据传递中没有写到子链的例子,一并加入下文了。
<div id="com">
<my-com ref="refss">Hello</my-com>
<my-com :name="name"></my-com>
<button @click="refs">点击</button>
</div>
<script>
Vue.component('my-com',{
template:'/<div><div><h2>这是一个组件</h2>' +
'<slot><my-com-2>{{name}}</my-com-2></slot>' +
'</div></div>/',
data:function () {
return{message:"global Component"}
},
props:['name']
}
);
Vue.component('my-com-2', {
template: '<div>我是第二个组件<slot></slot></div>'
}
);
new Vue({
el:"#com",
data:{name:"apple"},
methods:{
refs(){
//子链
alert(this.$refs.refss.message);
alert(this.$children[0].message)
}
}
});
</script>