分类:默认插槽、具名插槽、作用域插槽
默认插槽:让父组件可以向子组件指定位置插入html结构,也是一种组件通信的方式,适用于父组件(App)===>子组件(MyFooter)
默认插槽的App组件
<template>
?<div class="container">
? ?<!-- 普通写法 -->
? ?<!-- title、listDate的位置为标签属性。 -->
? ?<MyFooter title="游戏" :listDate="games"/>
?
? ?<!-- 下面都是默认插槽的书写形式-->
? ?<!-- Vue会将img标签的内容解析后在传给MyFooter组件中的slot插槽中。故将普通写法:listDate="foods"删除掉 -->
? ?<!-- 标签体的位置为:<MyFooter>标签体</MyFooter> ? -->
? ?<MyFooter title="美食" >
? ? ?<img src="图片地址" alt="">
? ?</MyFooter>
?
? ?<MyFooter title="游戏" >
? ? ? <ul>
? ? ? ? ? ?<li v-for="(item,index) in games" :key="index" >{{ item }}</li>
? ? ? ?</ul>
? ?</MyFooter>
?
? ?<MyFooter title="电影" >
? ? ?<!-- controls让视频可以通过点击控制播放 -->
? ? ? ? <video controls src="视频地址"></video>
? ?</MyFooter>
? ? ?
? ?<router-view />
?</div>
</template>
<script>
import MyFooter from './components/MyFooter.vue';
export default {
?name: 'App',
?components: { MyFooter },
?data() {
? ?return {
? ? ?foods: ['火锅', '薯条', '汉堡'],
? ? ?games: ['只狼', '大表哥', '黑神话悟空'],
? ? ?files: ['《深海》', '《战狼》', '《流浪地球》']
? }
}
}
</script>
<style lang="less" scoped>
.container {
?display: flex;
?justify-content: space-around
}
img {
?width: 100%;
}
video {
?width: 100%;
}
</style>
?
默认插槽的MyFooter组件
<template>
? ?<div class="category">
? ? ? ?<h3>{{ title }}分类</h3>
? ? ? ?<!-- 普通写法 -->
? ?<!-- 普通写法通过props将listDate传过来进行展示 -->
? ? ? ?<ul>
? ? ? <li ?v-for="(item,index) in listDate" :key="index" >{{ item }}</li> ?
? </ul>
<!-- 插槽写法 -->
? ? ? ?<!-- <slot></slot>为默认插槽,挖个坑等使用的组件填充坑的内容 -->
? ? ? ?<slot>如果图片或视频未展示,展示此处的文字</slot>
? ? ?
? ?</div>
</template>
?
<script>
export default {
? ?name: 'MyFooter',
? ?//这里保留应该只保留title,listDate仅是普通写法需求
? ?props: ['title','listDate'],
}
</script>
<style scoped lang="css">
? ?.category {
? ? ? ?background-color: skyblue;
? ? ? ?width: 200px;
? ? ? ?height: 300px;
? }
? ?h3 {
? ? ? ?text-align: center;
? }
</style>
?
具名插槽的App
具名插槽的给MyFooter的slot标上名字name="xxx",在App组件中使用那个插槽则slot="xxx"。进行相互匹配
<template>
?<div class="container">
?
? ?<!-- 有名插槽 -->
? ?<!-- title的位置为标签属性。-->
? ?<MyFooter title="美食" >
? ? ?<!-- 给img、a匹配相应的插槽名字,对应相应组件中的插槽 -->
? ? ?<img slot="center" src="图片地址" alt="">
? ? ?<a slot="footer" href="网址地址">美食地址</a>
? ? ?<a slot="footer" href="网址地址">电影地址</a>
? ?</MyFooter>
?
? ?<MyFooter title="游戏" >
? ? ? <ul slot="center">
? ? ? ? ? ?<li ?v-for="(item,index) in games" :key="index" >{{ item }}</li>
? ? ? </ul>
? ? ? <div slot="footer">
? ? ? ? ?<a slot="footer" href="网址地址">热门推荐</a>
? ? ? ? ?<a slot="footer" href="网址地址">网络共享</a>
? ? ? </div>
? ? ?
? ?</MyFooter>
?
? ?<MyFooter title="电影" >
? ? ?<!-- controls让视频可以通过点击控制播放 -->
? ? ? ? <video slot="center" controls src="视频地址"></video>\
? ? ? ? <!-- template让下列的代码少了一层div 同时可以将slot="footer"去掉,改成在template标签属性的位置使用 v-slot:footer -->
? ? ? ? <template>
? ? ? ? ? ?<div slot="footer">
? ? ? ? ? ? ? ?<a slot="footer" href="网址地址">动漫</a>
? ? ? ? ? ? ? ?<a slot="footer" href="网址地址">生活</a>
? ? ? ? ? ?</div>
? ? ? ? ? ?<a slot="footer" href="网址地址">动画片</a>
? ? ? ? </template>
? ?</MyFooter>
? ?<router-view />
?</div>
</template>
<script>
import MyFooter from './components/MyFooter.vue';
export default {
?name: 'App',
?components: { MyFooter },
?data() {
? ?return {
? ? ?foods: ['火锅', '薯条', '汉堡'],
? ? ?games: ['只狼', '大表哥', '黑神话悟空'],
? ? ?files: ['《深海》', '《战狼》', '《流浪地球》']
? }
}
}
</script>
<style lang="less" scoped>
.container {
?display: flex;
?justify-content: space-around
}
img {
?width: 100%;
}
video {
?width: 100%;
}
</style>
具名插槽的MyFooter
<template>
? ?<div class="category">
? ? ? ?<h3>{{ title }}分类</h3>
? ?
? ? ? ?<!-- <slot name=""></slot>为具名插槽,挖个坑等使用的组件填充坑的内容 -->
? ? ? ?<slot name="center">如果图片或视频未展示,展示此处的文字</slot>
? ? ? ?<slot name="footer">如果图片或视频未展示,展示此处的文字</slot>
? ? ?
? ?</div>
</template>
?
<script>
export default {
? ?name: 'MyFooter',
? ?props: ['title'],
}
</script>
?
<style scoped lang="css">
? ?.category {
? ? ? ?background-color: skyblue;
? ? ? ?width: 200px;
? ? ? ?height: 300px;
? }
? ?h3 {
? ? ? ?text-align: center;
? }
</style>
作用域插槽理解:
1、和上面两种插槽不同,作用域插槽数据(games) 在组件(MyFooter)但数据的结构需要组件的使用者(App)来决定
2、在MyFooter通过slot传给App,App组件通过scope进行接收。
App组件(vm)的管家。App不仅是组件,也管理所有的组件
<template>
?<div class="container">
?
? ?<MyFooter title="游戏" >
? ? ?<!-- 要想接收MyFooter传过来的games需要写成template形式通过scope来接收传过来的值,注意这里不是scoped而是scope。 -->
? ? ?<template scope="boy">
? ? ? ? ?<ul >
? ? ? ? ? ?<!-- 通过{{ games }}可以知道,只有boy.games才可以拿到数组,games是MyFooter传过来的数组是不可以修改的。 -->
? ? ? ? ? ? ?<li ?v-for="(item, index) in boy.games" :key="index" >{{ item }}</li>
? ? ? ? </ul>
? ? ?</template>
? ?</MyFooter>
?
? ?<MyFooter title="游戏" >
? ? ?<!-- 可以将scope="xxx"改成slot-scope="xxx"。slot-scope="xxx"是新的书写方式 -->
? ? ?<template scope="boy">
? ? ? ? ?<ol >
? ? ? ? ? ? ?<li ?v-for="(item, index) in boy.games" :key="index" >{{ item }}</li>
? ? ? ? </ol>
? ? ?</template>
? ?</MyFooter>
?
? ?<MyFooter title="游戏" >
? ? ?<!-- 用ES6的形式写成{games},遍历的时候可以直接写games -->
? ? ?<template scope="{games}">
? ? ? ? ? ? ?<h4 ?v-for="(item, index) in games" :key="index" >{{ item }}</h4>
? ? ?</template>
? ? ?
? ?</MyFooter>
?
? ?<router-view />
?</div>
</template>
<script>
import MyFooter from './components/MyFooter.vue';
export default {
?name: 'App',
?components: { MyFooter }
}
</script>
<style lang="less" scoped>
.container {
?display: flex;
?justify-content: space-around
}
img {
?width: 100%;
}
video {
?width: 100%;
}
</style>
?
作用域插槽的MyFooter组件
<template>
? ?<div class="category">
? ? ? ?<h3>{{ title }}分类</h3>
? ? ? ?<!-- :games="games"的意思是谁往插槽放数据games就传给谁 -->
? ? ? <slot :games="games"></slot>
? ?</div>
</template>
?
<script>
export default {
? ?name: 'MyFooter',
? ?props: ['title','listDate'],
? ?data(){
? ? ? ?return {
? ? ? ? ? ?games: ['只狼', '大表哥', '黑神话悟空'],
? ? ? }
? }, ?
}
</script>
?
<style scoped lang="css">
? ?.category {
? ? ? ?background-color: skyblue;
? ? ? ?width: 200px;
? ? ? ?height: 300px;
? }
? ?h3 {
? ? ? ?text-align: center;
? }
</style>
?