1. 概述
slot翻译为插槽,在生活中,我们也见过许多插槽,比如电源插座,USB插口等,这些都是插槽,它们起着各自的作用。
在组件中,我们可以通过插槽slot来添加各自的功能,有助于增强组件的扩展性。
比如在一个组件中,我们想多次调用,但每次调用组件后又想让它们有不同的地方,那么我们就可以在组件中预留插槽,然后在插槽中添加它们的不同。
2. 基本使用
<body>
<script src='../js/vue.js'></script>
<div id='app'>
<cpn><button>click</button></cpn>
<cpn><input type="text"></cpn>
<cpn><a href="">百度</a></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h1>相同的地方</h1>
<slot>不同的地方</slot>//声明插槽
</div>
</template>
<script>
const cpn = {
template: '#cpn'
}
const app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
components: {
cpn
}
});
</script>
</body>
这里在子组件中声明了一个插槽slot,然后在调用时给不同cpn内部添加自己想要的元素,它会将cpn内部添加的所有元素替代掉slot插槽,如果没有添加,则会默认显示slot内部元素信息。
3. 具名插槽
所谓具名插槽就是给插槽添加了name属性,然后在使用时,通过cpn内的slot属性等于插槽名来使用插槽。
<body>
<script src='../js/vue.js'></script>
<div id='app'>
<cpn><span slot="slot2">已替换</span></cpn>
<cpn>123</cpn>
</div>
<template id="cpn">
<div>
<h1>相同的部分</h1>
<slot name='slot1'><span>left</span> </slot>
<slot name='slot2'><span>center</span></slot>
<slot name='slot3'><span>right</span> </slot>
<slot>我是默认的部分</slot>
</div>
</template>
<script>
const cpn = {
template: '#cpn'
}
const app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
components: {
cpn
}
});
</script>
</body>
这里在子组件中声明了4个插槽,前三个分别设置了name属性,在父组件中调用了两个cpn
第一个对name=‘slot2’的插槽进行了更换,其余没变
第二个没声明slot属性,直接改用内部值为123
结果如下
可以看出
第一个cpn确实已经对第二个插槽发生了修改
第二个cpn
由于没有声明slot属性,因此只是将123替换了也未声明name属性的插槽
4. 作用域插槽
什么叫作用域插槽?
顾名思义,插槽,还用上了作用域!
我们知道,data里的数据只能在当前组件里使用,如果想要使用还得组件传值,那如果我么想要在父组件里拿到子组件里的数据并按照自己想要的格式显示,有什么好的方法吗?
那就是作用域插槽
其实就是通过在slot标签上添加 v-bind 属性将数据动态绑定,然后父组件就可以通过在引用组件里的最外层标签的 slot-scope属性上获得。
步骤:
1.子组件通过v-bind属性动态绑定数据
2.父组件在引用组件cpn里声明一个外层div(vue2.5.x以下只能用template),在div上通过slot-scope(作用域插槽)等于slot获取到子组件里的插槽属性
3.然后就可以调用得到的插槽里的数据,就能按照自己想要的形式显示
上代码
<body>
<script src='../js/vue.js'></script>
<div id='app'>
<cpn>
<div slot-scope='slot'>
<h3>1.无序列表显示</h3>
<ul>
<li v-for='item in slot.movies'>{{item}}</li>
</ul>
<h3>2.通过 ' - '隔开显示</h3>
<span>{{slot.movies.join(' - ')}}</span>
</div>
</cpn>
</div>
<template id="cpn">
<div>
<slot :movies='movies'></slot>
</div>
</template>
<script>
const app = new Vue({
el: '#app',
data: {
},
components: {
cpn: {
template: '#cpn',
data() {
return {
movies: ['金刚大战哥斯拉', '极速蜗牛', '复仇者联盟']
}
}
}
}
});
</script>
</body>