vue插槽的作用
Vue插槽是Vue中常见的一种组件间的相互通信方式,作用是让父组件可以向子组件指定位置插入html结构,适用于父组件===>子组件,在要接收数据的组件页面通过<slot></slot>标签来表示,简单来说,就是通过此标签来起到占位的作用,而要插入的内容也会对应到标签所在的位置。
1.默认插槽
默认插槽是插槽最基本的方式:
首先在父组件App.vue中引入子组件,并在引入的子组件标签内插入需要的html元素,在子组件中把需要用插槽的地方用<slot></slot>标签替代:
在App.vue中引入子组件,使用子组件,并且声明需要的数据:
1.1.引入组件
import StudyM from './components/StudyM.vue'
1.2.使用组件
<template> <div id="app"> <!-- 默认插值 --> <StudyM title="游戏列表"> <ul> <li v-for="game , index in games" :key="index">{{game}}</li> </ul> </StudyM> <StudyM title="推荐音乐"> <ul> <li v-for="music , index in musics" :key="index">{{music}}</li> </ul> </StudyM> <StudyM title="电影推荐"> <ul> <li v-for="movie , index in movies" :key="index">{{movie}}</li> </ul> </StudyM> </div> </template>
1.3.添加数据
data(){ return{ games:['英雄联盟', '炉石传说', '穿越火线', 'QQ飞车', '吃鸡'], musics:['迷途羔羊', '红玫瑰', '富士山下', '麻雀', '妈妈的话', '故乡'], movies:['蜘蛛侠', '复仇者联盟', '金刚狼', '触不可及', '唐人街探案','当幸福来敲门'] } }
1.4.完整的代码
父组件App.vue代码:
<template> <div id="app"> <!-- 默认插值 --> <StudyM title="游戏列表"> <ul> <li v-for="game , index in games" :key="index">{{game}}</li> </ul> </StudyM> <StudyM title="推荐音乐"> <ul> <li v-for="music , index in musics" :key="index">{{music}}</li> </ul> </StudyM> <StudyM title="电影推荐"> <ul> <li v-for="movie , index in movies" :key="index">{{movie}}</li> </ul> </StudyM> </div> </template> <script> //引入组件 import StudyM from './components/StudyM.vue' export default { name: 'App', components: { StudyM }, data(){ return{ games:['英雄联盟', '炉石传说', '穿越火线', 'QQ飞车', '吃鸡'], musics:['迷途羔羊', '红玫瑰', '富士山下', '麻雀', '妈妈的话', '故乡'], movies:['蜘蛛侠', '复仇者联盟', '金刚狼', '触不可及', '唐人街探案','当幸福来敲门'] } } } </script> <style scoped> #app{ display: inline-flex; justify-content: center; } </style>
子组件StudyM.vue代码:
<template> <div class="box"> <h4>{{title}}</h4> <slot></slot> </div> </template> <script> export default { name:'StudyM', props:['title'], } </script> <style scoped> .box{ margin: 20px; width: 200px; height: 200px; background-color: aqua; } h4{ text-align: center; background-color: rgb(127, 236, 113); } </style>
效果图
2.具名插槽
简单来说,所谓的具名插槽就是有名字的插槽。
那它和默认插槽有什么不同呢?
有时候我们会遇到这种场景,在一个组件中,我们虽然可以复用组件的结构,但是往往,有时候我们会遇到一个组件多用,但是结构稍微有所差别的情况,这时,就会用得到具名插槽。
2.1.首先在要插入html的部分需要一个<template>标签包裹住各个部分:
<!-- 具名插槽的写法一 --> <template slot="one"> <ul> <li v-for="game , index in games" :key="index">{{game}}</li> </ul> </template>
2.2.其次,当给<template>标签绑定slot="name"属性时,需要在子组件中对应每个<template>给出一个<slot>并且添加上name属性:
<div class="box"> <h4>{{title}}</h4> <slot name="one"></slot> <slot name="tow"></slot> </div>
2.3.完整代码
父组件App.vue代码:
<template> <div id="app"> <!-- 默认插值 --> <StudyM title="游戏列表"> <!-- 具名插槽的写法一 --> <template slot="one"> <ul> <li v-for="game , index in games" :key="index">{{game}}</li> </ul> </template> <!-- 具名插槽的写法二 --> <template v-slot:tow> <a href="https://lol.qq.com/main.shtml">英雄联盟官网由此进入</a><br/><br> <a href="https://www.wegame.com.cn/">了解更多游戏</a> </template> </StudyM> <StudyM title="推荐音乐"> <template slot="one"> <ul> <li v-for="music , index in musics" :key="index">{{music}}</li> </ul> </template> <template slot="tow"> <button>点击进入QQ音乐</button> <button>点击进入网易云音乐</button> </template> </StudyM> <StudyM title="电影推荐"> <template slot="one"> <ul> <li v-for="movie , index in movies" :key="index">{{movie}}</li> </ul> </template> <template slot="tow"> <video controls src="https://www.oppo.com/content/dam/oppo/product-asset-library/find/find-n/v1/assets/tvc-preview-3d0357.mp4"></video> </template> </StudyM> </div> </template> <script> //引入组件 import StudyM from './components/StudyM.vue' export default { name: 'App', components: { StudyM }, data(){ return{ games:['英雄联盟', '炉石传说', '穿越火线', 'QQ飞车', '吃鸡'], musics:['迷途羔羊', '红玫瑰', '富士山下', '麻雀', '妈妈的话', '故乡'], movies:['蜘蛛侠', '复仇者联盟', '金刚狼', '触不可及', '唐人街探案','当幸福来敲门'] } } } </script> <style scoped> #app{ display: inline-flex; justify-content: center; } video{ width: 100%; } </style>
子组件StudyM.vue代码:
<template> <div class="box"> <h4>{{title}}</h4> <slot name="one"></slot> <slot name="tow"></slot> </div> </template> <script> export default { name:'StudyM', props:['title'], } </script> <style scoped> .box{ margin: 20px; width: 300px; padding: 20px; background-color: aqua; } h4{ text-align: center; background-color: rgb(127, 236, 113); } </style>
效果图
tips: 值得注意的是,在具名插槽当中,我们不仅要使用到<template>标签,而且还要在其中声明slot="name"属性,在子组件中的<slot>标签中接收过来的name的属性值。
3.作用域插槽
作用域插槽的特点,数据在子组件中,但是根据子组件传过来的数据生成的结构需要组件的使用者(父组件)来决定,也就是说,作用域插槽的不同之处就在于,数据不在父组件身上,而是在子组件身上,且组件的结构和内容由父组件决定(父组件可以自行添加自定义内容)。作用域组件限定了组件内结构和数据的展示范围,以便在开发中我们可以根据一个组件而不断变换其中的内容和结构。
3.1.使用作用域插槽,数据在子组件中,需要通过数据绑定传给使用者插入html的部分:
<div class="box"> <h4>{{title}}</h4> <!-- 把数据传给插入的html部分 --> <slot :movies="movies"></slot> </div>
3.2.此时,在使用者组件(父组件)中,使用<template>中的scope=“Data”属性将数据传递过来:
<StudyM title="游戏列表"> <template scope="one"> <!-- 第一种结构 --> <ul> <li v-for="m,index in one.movies" :key="index">{{m}}</li> </ul> </template> </StudyM>
3.3.完整代码
父组件App.vue代码:
<template> <div id="app"> <!-- 默认插值 --> <StudyM title="游戏列表"> <template scope="one"> <!-- 第一种结构 --> <ul> <li v-for="m,index in one.movies" :key="index">{{m}}</li> </ul> </template> </StudyM> <StudyM title="游戏列表"> <template scope="one"> <!-- 第二种结构 --> <ol> <li v-for="m,index in one.movies" :key="index">{{m}}</li> </ol> </template> </StudyM> <StudyM title="游戏列表"> <template scope="one"> <!-- 第三种结构 --> <h4 v-for="m,index in one.movies" :key="index">{{m}}</h4> </template> </StudyM> </div> </template> <script> //引入组件 import StudyM from './components/StudyM.vue' export default { name: 'App', components: { StudyM }, } </script> <style scoped> #app{ display: inline-flex; justify-content: center; } video{ width: 100%; } </style>
子组件StudyM.vue代码:
<template> <div class="box"> <h4>{{title}}</h4> <!-- 把数据传给插入的html部分 --> <slot :movies="movies"></slot> </div> </template> <script> export default { name:'StudyM', props:['title'], data(){ return{ movies:['蜘蛛侠', '复仇者联盟', '金刚狼', '触不可及', '唐人街探案','当幸福来敲门'] } } } </script> <style scoped> .box{ margin: 20px; width: 300px; padding: 20px; background-color: aqua; } h4{ text-align: center; background-color: rgb(127, 236, 113); } </style>
效果图
参考---https://blog.csdn.net/weixin_53614367/article/details/123512913
标签:Vue,name,StudyM,vue,插槽,title,详解,组件 From: https://www.cnblogs.com/pwindy/p/17388153.html