使用slot的原因
在使用组件时,经常会用到一些相似的组件,这些组件有很多共性,但又不完全相同。如果将这些组件都封装成不同的组件,会出现很多重复的代码,难免浪费资源。
为了提高组件的复用性和可移植性,组件中如果有些地方可以让用户来决定放什么东西,那组件的使用就变得非常灵活。slot正是为了解决这个问题。
slot的基本使用
slot作为标签使用,在需要用户动态设置的地方,用slot标签代替。用户在使用标签时,用相应的标签代替slot标签。如下所示:
在相应的位置加入<slot></slot>标签,slot标签具体替换为什么标签由用户在使用时,在组件内部指定。
<div id="app">
<mycpn><p>我是slot的p标签</p></mycpn>
<mycpn><button>我是slot的button标签</button></mycpn>
</div>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>{{title}}</h2>
<slot></slot>
</div>
</template>
<script>
//相当于vue的子组件
const mycpn={
template:'#cpn',
data(){
return {
title: '我是子组件'
}
}
}
//创建并注册组件
Vue.component('mycpn',mycpn);
//vue相当于父组件
const vue = new Vue({
el:"#app",
data:{
title:"我是父组件"
},
components:{
mycpn:mycpn
}
});
</script>
在使用组件时,分别用p标签和button标签替换slot,效果如下:
如果在使用组件时,发现某一个标签比较常用,可以给slot设置默认值,这样就不用每次都写替换slot的标签,默认就有一个标签。比如,设置button为slot默认标签:
<div id="app">
<mycpn><p>我是slot的p标签</p></mycpn>
<mycpn><button>我是slot的button标签</button></mycpn>
<mycpn></mycpn>
<mycpn></mycpn>
</div>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>{{title}}</h2>
<slot><button>按钮</button></slot>
</div>
</template>
<script>
//相当于vue的子组件
const mycpn={
template:'#cpn',
data(){
return {
title: '我是子组件'
}
}
}
//创建并注册组件
Vue.component('mycpn',mycpn);
//vue相当于父组件
const vue = new Vue({
el:"#app",
data:{
title:"我是父组件"
},
components:{
mycpn:mycpn
}
});
</script>
效果如下:后面两个组件没有给slot设置替换标签,显示默认值。
如果在给slot设置替换标签时设置了多个标签,多个标签会一起替换掉slot。不是一对一的替换。如下:
在组件中给slot设置三个标签,<p>,<span>,<button>
<div id="app">
<mycpn><p>我是slot的p标签</p></mycpn>
<mycpn><button>我是slot的button标签</button></mycpn>
<mycpn><p>我是p标签</p>
<span>我是span标签</span>
<button>我是button标签</button>
</mycpn>
<mycpn></mycpn>
</div>
<script src="../js/vue.js"></script>
<template id="cpn">
<div>
<h2>{{title}}</h2>
<slot><button>按钮</button></slot>
</div>
</template>
<script>
//相当于vue的子组件
const mycpn={
template:'#cpn',
data(){
return {
title: '我是子组件'
}
}
}
//创建并注册组件
Vue.component('mycpn',mycpn);
//vue相当于父组件
const vue = new Vue({
el:"#app",
data:{
title:"我是父组件"
},
components:{
mycpn:mycpn
}
});
</script>
效果如下: