Vue 实现了一套内容分发的 API,将<slot>
元素作为承载分发内容的出口,这是vue文档上的说明。具体来说,slot就是可以让你在组件内添加内容的‘空间’。总共分为三种:默认插槽 具名插槽 作用域插槽。
举一个例子说明插槽在父子组件间的作用:
将父组件的内容放到子组件指定的位置叫做内容分发,这就是slot插槽的作用,就是父组件引用子组件的同时,把父组件的内容放到子组件里面去。
比如我在子组件NavHeader中定义了一个slot标签,如下:
<div class="content">
<slot></slot> //子组件NavBread
</div>
在父组件中的该组件(nav-bread)名称里直接写需要的内容:
<nav-bread>
<span slot="bread">web秀</span>
</nav-bread>
这时候编译的代码就是这样的:
<div class="content">
<span>web秀</span>
</div>
默认插槽举例:
cartoonvue.vue
<div class="container">
<categoryvue title="美食">
<img src="https://img1.baidu.com/it/u=3603349077,2543717877&fm=253&app=120&size=w931&n=0&f=PNG&fmt=auto?sec=1667754000&t=b6dde1b42b636e1c035c2b9af6c268b5">
</categoryvue>
<categoryvue title="游戏">
<ul>
<li v-for="(g,index) in games" :key="index">{{g}}</li>
</ul>
</categoryvue>
<categoryvue title="电影">
<video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
</categoryvue>
</div>
扩展 视频在浏览器上可以显示播放(controls 这个必须加不然视频没法播放)
<video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
App.vue
<!-- 默认插槽:单个slot -->
<template>
<div class="categorystu">
<h3>{{title}}</h3>
<slot>默认插槽:我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
</div>
</template>
<!--组件数据交互-->
<script>
//这样写法更加简洁,这样用的多
export default {
//代表组件名称,最好与 school.vue中的school一致
name:'categoryvue',
props:['title']
}
</script>
<!--组件样式-->
<style>
.categorystu{
background-color: skyblue;
width:200px;
height: 300px;
}
h3{
text-align: center;
background-color: orange;
}
img{
width: 100%;
}
video{
width: 100%;
}
</style>
具名插槽举例:多个slot用name区别,App中相同name的不同数据都可以对应组件里面同一个<slot>
标签
categoryvue2.vue
<!-- 具名插槽:多个slot用name区别 对应App.vue中name-->
<template>
<div class="categorystu">
<h3>{{title}}</h3>
<slot name="zhong">具名插槽:我是一些默认值,当使用者没有传递具体结构时,我会出现zhong</slot>
<slot name="dibu">具名插槽:我是一些默认值,当使用者没有传递具体结构时,我会出现dibu</slot>
</div>
</template>
<!--组件数据交互-->
<script>
//这样写法更加简洁,这样用的多
export default {
//代表组件名称,最好与 school.vue中的school一致
name:'categoryvue2',
props:['title']
}
</script>
<!--组件样式-->
<style>
.categorystu{
background-color: skyblue;
width:200px;
height: 300px;
}
h3{
text-align: center;
background-color: orange;
}
img{
width: 100%;
}
video{
width: 100%;
}
h4{
text-align: center;
}
</style>
App.vue
<!--具名插槽-->
<div class="container">
<categoryvue2 title="美食">
<img slot="zhong" src="https://img1.baidu.com/it/u=3603349077,2543717877&fm=253&app=120&size=w931&n=0&f=PNG&fmt=auto?sec=1667754000&t=b6dde1b42b636e1c035c2b9af6c268b5">
<a slot="dibu" href="https://www.meituan.com/">更多美食</a>
</categoryvue2>
<categoryvue2 title="游戏">
<ul slot="zhong">
<li v-for="(g,index) in games" :key="index">{{g}}</li>
</ul>
<!--这里为了一个dibu模板slot显示两个,需要加空格样式,所以单独写一个div class中定义,直接在<a></a> 之间写<br>不起作用因为组件模板中没有定义,而且App里面直接<br>也失效带不到组件模板里面-->
<div class="dibucss" slot="dibu">
<a href="https://code.51.com/jh/g51yx/i17/26ds5.html?g=bgjzqxc_1100145?rq=0&bd_vid=10419870625563131241">单机游戏1</a>
<a href="https://pvp.qq.com/">网络游戏2</a>
</div>
</categoryvue2>
<categoryvue2 title="电影">
<video slot="zhong" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
<!--原本这是div,但是没必要生成,用template不生成最终的dom元素,省一层div结构-->
<template slot="dibu"> <!--用template 也可以这样写 <template v-slot:dibu> 效果一样 但是div里面不行注意-->
<div class="dibucss">
<a href="https://www.1905.com/">经典电影</a>
<a href="https://www.1905.com/">热门电影</a>
<a href="https://www.1905.com/">推荐电影</a>
</div>
<h4>欢迎来观看小悦悦</h4>
</template>
</categoryvue2>
</div>
扩展 template标签:不生产具体的dom结果,用于替换div,写div也一样主要也没必要生成div。
作用域插槽举例:不像上面两个slot,这个是数据在子组件里面,通过slot中:cars获取数据,等App.vue把结构传到子组件后,自组件再把准备好的数据灌进结构里面,最后把带有数据的结构进行展示。
categoryvue3.vue
<!-- 作用域插槽-->
<template>
<div class="categorystu">
<h3>{{title}}</h3>
<slot :cars="cars" msg="小悦悦你好啊!">作用域插槽:我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
</div>
</template>
<!--组件数据交互-->
<script>
//这样写法更加简洁,这样用的多
export default {
//代表组件名称,最好与 school.vue中的school一致
name:'categoryvue3',
data(){
return{
cars:['法拉利','兰博基尼','奥迪','宝马'],
}
},
props:['title']
}
</script>
<!--组件样式-->
<style>
.categorystu{
background-color: skyblue;
width:200px;
height: 300px;
}
h3{
text-align: center;
background-color: orange;
}
img{
width: 100%;
}
video{
width: 100%;
}
h4{
text-align: center;
}
</style>
App.vue
hahads => { "cars": [ "法拉利", "兰博基尼", "奥迪", "宝马" ] }
<div class="container">
<!-- <categoryvue3 title="美食">
<img src="https://img1.baidu.com/it/u=3603349077,2543717877&fm=253&app=120&size=w931&n=0&f=PNG&fmt=auto?sec=1667754000&t=b6dde1b42b636e1c035c2b9af6c268b5">
</categoryvue3> -->
<categoryvue3 title="汽车">
<!--slot-scope 这里随便定义不需要对应 hahads就是categoryvue3中cars的具体数据-->
<!--作用域插槽写法template必须写的!!-->
<!--或者es6语法 直接slot-scope="cars" 然后下面直接in cars-->
<template slot-scope="hahads">
<!-- hahads => { "cars": [ "法拉利", "兰博基尼", "奥迪", "宝马" ] }-->
<!--<ol> 有序 <ul>无序-->
<ol>
<!--cars具体数据在categoryvue3定义-->
<li style="color:red" v-for="(c,index) in hahads.cars" :key="index">{{c}}</li>
</ol>
<!--获取组件里面msg="小悦悦你好啊!"的 小悦悦你好啊!-->
<h4>{{hahads.msg}}</h4>
</template>
</categoryvue3>
<!-- <categoryvue3 title="电影">
<video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
</categoryvue3> -->
</div>
注意:
- 这里用作用域插槽那么
<template slot-scope="hahads">
template是必须加的。 <template slot-scope="hahads">
可以用es6写法<template slot-scope="{cars}">
直接拿到cars里面数据。- 标签
<ol>
有序<ul>
无序