一、需求
有三个Category
组件,展示不同的内容。
需求:美食模块需要展示图片,游戏模块还是文字,电影模块展示预告片。
<!--App组件-->
<template>
<div class="container">
<Category :listData="foods" title="美食"> </Category>
<Category :listData="games" title="游戏"> </Category>
<Category :listData="films" title="电影"> </Category>
</div>
</template>
<script>
data () {
return {
foods: ['火锅', '烧烤', '小龙虾'],
games: ['超级玛丽', '魂斗罗'],
films: ['寻梦环游记', '小黄人大眼萌']
}
}
</script>
<!--Category组件-->
<template>
<div class="content">
<h3 class="title">{{ title }}</h3>
<ul>
<li v-for="(item, index) in listData" :key="index">{{ item }}</li>
</ul>
</div>
</template>
<script>
props: ['listData', 'title']
</script>
二、插槽
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式。
1. 默认插槽
<!--父组件中:-->
<Category>
<div>html结构1</div>
</Category>
<!--子组件中:-->
<template>
<div>
<!-- 定义插槽,相当于在这里挖了个坑,等待组件的使用者来填充 -->
<slot>插槽默认内容...</slot>
</div>
</template>
插槽里的这些样式放在App里也行,放在Category里也行。
2. 具名插槽
当子组件中包含多个插槽时,需要给每个插槽起名字
起名字:指定name
属性
使用具名插槽:
slot = '插槽名'
- 如果使用了
template
, 还可以v-slot:footer
来指定使用哪个插槽(这种方式只有template可以这样写)
子组件:
<!--Category组件-->
<template>
<div class="content">
<h3 class="title">{{ title }}</h3>
<slot name="center"></slot>
<slot name="footer"></slot>
</div>
</template>
父组件:
<!--App.vue组件-->
<div class="container">
<Category title="美食">
<img slot="center" src="../public/food.jpg" alt="" />
<div slot="footer" class="foot">
<a href="">更多美食</a>
<a href="">更多美食</a>
</div>
</Category>
<Category title="游戏">
<ul slot="center">
<li v-for="(g, index) in games" :key="index">{{ g }}</li>
</ul>
<a href="#" slot="footer">单机游戏</a>
</Category>
<Category title="电影">
<video src="https://vjs.zencdn.net/v/oceans.mp4"></video>
<template v-slot:footer>
<div class="foot">
<a href="http://www.atguigu.com">经典</a>
<a href="http://www.atguigu.com">热门</a>
<a href="http://www.atguigu.com">推荐</a>
</div>
</template>
</Category>
</div>
如果插槽不指定名称,使用的时候就会出现多个同样的内容
3. 作用域插槽
子组件通过插槽给父组件传值,必须要写template来接收传过来的值。
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
子组件Category
<template>
<div class="content">
<slot :films="films"></slot>
</div>
</template>
<script>
data () {
return {
films: ['寻梦环游记', '小黄人大眼萌']
}
}
</script>
父组件App.vue
<div class="container">
<Category>
<!-- template必须要写 -->
<template scope="scopeData">
<!--查看scopeData具体是什么-->
{{scopeData}}
<ul>
<li v-for="(item, index) in scopeData.films" :key="index"> {{ item }}</li>
</ul>
</template>
</Category>
</div>
1、 scopeData具体内容是什么?
是一个对象
2、获取scope数据的简单方式,解构赋值
<template scope="{films}">
<ul>
<li v-for="(item, index) in films" :key="index"> {{ item }}</li>
</ul>
</template>
3、获取数据还有一种方式
语法:slot-scope="{films}
<template slot-scope="{films}">...</template>
用哪种方式都行,是新旧api的原因。slot-scope
是新api获取数据的方式,scope
是旧api获取数据的方式