【vue(2)插槽】
插槽 --适用于父组件访问子组件
- 一、概念
- 1.概念
- 2.作用
- 3.本质
- 二、插槽的基本使用
- 三、插槽的分类
- 1.默认插槽
- 2.具名插槽
- 3.作用域插槽
一、概念
1.概念
- Slot 通俗的理解就是“占坑”,在组件模板中占好了位置,当使用该组件标签的时候,组件标签里面的内容就会自动填坑(替换组件模板中slot位置)
- 并且可以作为承载分发内容的出口
2.作用
允许你在
使用组件时
,向组件内部插入内容
(HTML、组件、甚至是函数),让组件可以根据这些内容进行渲染。
3.本质
- 插槽是 Vue 提供的一个“内容占位符”。
父组件
可以向这个“占位符”中插入任意内容
。子组件
可以决定这些内容在哪里显示
。
二、插槽的基本使用
- 插槽就是“占一个位置”,等别人来填内容
- 就像写了一个组件,里面留了一个空位,别人用这个组件的时候,可以自己决定空位放什么内容
举例来说,这里有一个 <FancyButton>
组件
<FancyButton>Click me! <!-- 插槽内容 -->
</FancyButton>
而 <FancyButton>
的模板是这样的
<button class="fancy-btn"><slot></slot> <!-- 插槽出口 -->
</button>
<slot>
元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。
最终渲染出的 DOM 是这样:
<button class="fancy-btn">Click me!</button>
三、插槽的分类
名称 | 说明 |
---|---|
默认插槽 | 插入内容,不指定名字 |
具名插槽 | 插入内容,指定名字 |
作用域插槽 | 插槽内容可以访问子组件的数据 |
1.默认插槽
我们要在页面显示三个类别,每个类别下面有不同的文字,本来是我们把数据传给子组件然后使用v-for遍历生成的文字信息,但是产品经理突然让你把美食类的下面换成图片,电影类下面换成视频,怎么搞?
子组件:
<template><div class="category"><h3>{{ title }}类</h3><ul><slot>我是一个插槽,当使用者没有传递具体结构时,我会出现</slot></ul></div>
</template>
父组件App.vue:
<template><div class="container"><Category title="美食"><!--往slot插入东西--><img src="http://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt=""></Category><Category title="游戏"><!--往slot插入东西--><li v-for="(game, index) in games" :key="index">{{ game }}</li></Category><Category title="电影"><!--往slot插入东西--><video controls src="http://clips.vorwaerts-gmbh.de/big_buck.bunny.mp4"></video></Category></div>
</template><script>
import Category from './components/Category.vue';export default {name: "App",components: { Category },data() {return {//foods: ['火锅', '烧烤', '小龙虾', '牛排'],games: ['战神4', '极品飞车', '鬼泣', '超级玛丽'],// films: ['《教父》', '《复仇者联盟》', '《绿皮书》', '《阿甘》']}},
}
</script>
2.具名插槽
子组件使用name属性起个名,父组件里面使用slot="名字"找到对应的坑位
父组件中:<template><div><Category><div slot="center">中间的结构</div><a slot="center" href="http://www.zzy.com">中间的结构</a><template v-slot:footer> 最新写法,要配合template使用<div>底部的结构</div><h4>欢迎你</h4></template></Category></div></template>子组件中:<template><div><!-- 定义插槽 --><slot name="center">插槽默认内容...</slot><slot name="footer">插槽默认内容...</slot></div></template>
3.作用域插槽
有一天,产品经理让你把每个部分的数据换个形式,换成下边这样,咋整?
这里就用到了作用域插槽,如果数据不在App中了,而在Category.vue中,然后App.vue要用到数据,这时我们就可以在Category.vue中使用slot标签给父组件App传值,写法很像当时父给子传值的props写法,在标签里搞个:games=“games”,然后用到插槽的地方必须使用template标签包裹,并且配置scope属性来接收数据,接过来的是一个对象
其实这个功能使用默认插槽完全可以实现,但是默认插槽是指数据在使用插槽的文件里的,那么如果数据在别的地方(比如本案例的Category.vue文件),就得用作用域插槽
Category.vue文件
<template><div class="category"><h3>{{ title }}类</h3><slot :games="games">默认内容</slot></div>
</template><script>
export default {name: 'Category',props: ['title'],data() {return {games: ['战神4', '极品飞车', '鬼泣', '超级玛丽']}},
};
</script>
App.vue文件
<template><div class="container"><Category title="游戏"><template scope="youxis"><!-- {{ youxis.games }} --><!-- { "games": [ "战神4", "极品飞车", "鬼泣", "超级玛丽" ] } --><ul><li v-for="(game, index) in youxis.games" :key="index">{{ game }}</li></ul></template></Category><Category title="游戏"><template scope="{games}"><ol><li v-for="(game, index) in games" :key="index">{{ game }}</li></ol></template></Category><Category title="游戏"><template slot-scope="{games: youxis}"><h4 v-for="(game, index) in youxis" :key="index">{{ game }}</h4></template></Category></div>
</template><script>
import Category from './components/Category.vue';
export default {name: "App",components: { Category },
}
</script>