【Vue 快速入门系列】3分钟掌握Vue中插槽的使用与理解

前言

  1. 插槽作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件

  2. 插槽分类:默认插槽、具名插槽、作用域插槽

  3. 理解插槽:数据在组件的自身或者是父组件在槽位传入,但根据数据生成的结构需要组件的使用者来决定(父级组件传入)。

通俗点来说:插槽就是子组件中的提供给父组件使用的一个占位符,用<slot></slot> 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件中的<slot></slot>标签。如果不使用插槽,父组件标签中的代码将会被忽略,合理的使用插槽功能会使我们写代码更加方便。今天就会结合下面一个小案例让大家融会贯通Vue中的插槽。

如图,展示出了三个列表,其中列表中的数据与定义都在父组件,子组件只进行了渲染工作。可以先看下面三幅图。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看完上面三幅图相信大家对这个小案例有了一定的了解,接下来要做的就是使用插槽,对列表内的内容进行定制,实现在父组件内定义子组件时将样式传进去,从而实现相同的列表模板渲染出不同的效果,这得益于插槽可以将父组件中包含的html样式传送给子组件固定的槽位。
在这里插入图片描述

接下来咱们一起看看插槽如何使用吧。

一、常规实现方式

这种实现方式会将html样式写在子组件内,实现之后可以发现子组件的内容已经写死,并没有办法在父组件实现更新与扩展。
核心代码(Lists组件):

<template>
  <div class="someOne">
    <h2>{{title}}名单</h2>
    <ul  v-show="title==='游戏'">
      <li v-for="(i, index) in mylis" :key="index">
        {{ i }}
      </li>
    </ul>
    <img v-show="title==='美食'" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
    <video v-show="title==='电影'" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
  </div>
</template>

二、匿名插槽

匿名插槽就是没有名字的插槽,如何使用完全按照Vue的规则进行分配,如下图每一个匿名插槽均会将该组件标签包含的模板渲染一遍。
vue渲染匿名插槽的规则是:将组件标签中包含的html完整的替换子组件内的插槽(子组件有多少个替换多少个)。
在这里插入图片描述
父组件的代码如下(App.vue):

<template>
  <div class="container">
  //Lists标签包含的所有内容均会挂载到Lists组件内的solt标签上
    <Lists title="游戏">
    /*
    	<Lists></Lists>之间的内容可以认为是父组件的一个槽位,页面渲染时会将槽位的内容放入子组件的插槽中
    */
      <ul>
        <li v-for="(i, index) in games" :key="index">
          {{ i }}
        </li>
      </ul>
      <div>Hello</div>
    </Lists>
    <Lists title="美食">
      <img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="" />
      <video
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      ></video>
    </Lists>
    <Lists title="电影">
      <video
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      ></video>
    </Lists>
  </div>
</template>

<script>
import Lists from "./components/Lists.vue";
export default {
  name: "App",
  components: {
    Lists,
  },
  data() {
    return {
      foods: ["火锅", "烧烤", "小龙虾", "牛排"],
      games: ["红色警戒", "穿越火线", "劲舞团", "超级玛丽"],
      films: ["《教父》", "《拆弹专家》", "《你好,李焕英》", "《尚硅谷》"],
    };
  },
};
</script>

<style scoped>
.container {
  display: flex;
  justify-content: space-around;
}
</style>

子组件代码如下(Lists.vue):

<template>
  <div class="someOne">
    <h2>{{title}}名单</h2>
    <!-- 以下操作是匿名插槽,使用者需要自定义内容,最后内容会插在这个插槽内 -->
    <!-- 如果是两个插槽的话,会将传进来的东西放两遍,多个放多遍 -->
    <slot></slot>
    <slot></slot>
  </div>
</template>

<script>
export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: "Lists",
  props: ["title"],
};
</script>

<style>
.someOne{
    width: 200px;
    height: 300px;
    background-color: rgb(0, 184, 144);
    margin-top: 100px;
}
h2{
    text-align: center;
    background-color: #F96B36;
}
img{
    width: 100%;
}
video{
    width: 100%;
}
</style>

三、具名插槽

具名插槽就是有名字的插槽,如何使用完全按照Vue的规则进行分配,渲染时根据名字进行精准渲染,没有内容传进来就使用默认内容。
vue渲染具名插槽的规则是:将组件中包含的html有规则的替换子组件内相应的具名插槽(精准的替换)。
第一步就是在使用组件时定义模板要挂载到哪个插槽上
例:将图片挂载到插槽名为center的槽位

<img slot="center"
  src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg"
  alt=""
/>

第二步就是在组件内定义插槽的位置。
例:这个槽位等待等待slot="center"的标签挂载。

<slot name="center">我是一个插槽,我位于中间,当没有数据传过来的时候我会显示</slot>

在这里插入图片描述

在这里插入图片描述

父组件(App.vue)

<template>
  <div class="container">
    <Lists title="游戏">
    //第一种传入方式
      <ul slot="center">
        <li v-for="(i, index) in games" :key="index">
          {{ i }}
        </li>
      </ul>
      <div class="centerdiv" slot="footer">
        <a href="#">单击游戏</a>
        <a href="#">网络游戏</a>
      </div>
    </Lists>
    <Lists title="美食">
      <img slot="center"
        src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg"
        alt=""
      />
      <a href="#" slot="footer">更多美食</a>
    </Lists>
    <Lists title="电影">
      <video slot="center"
        controls
        src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
      ></video>
      //第二种传入方式
      <template v-slot:footer>
        <ul>
          <li>热门电影</li>
          <li>经典电影</li>
          <li>豪华电影</li>
        </ul>

      </template>
    </Lists>
  </div>
</template>

<script>
import Lists from "./components/Lists.vue";
export default {
  name: "App",
  components: {
    Lists,
  },
  data() {
    return {
      foods: ["火锅", "烧烤", "小龙虾", "牛排"],
      games: ["红色警戒", "穿越火线", "劲舞团", "超级玛丽"],
      films: ["《教父》", "《拆弹专家》", "《你好,李焕英》", "《尚硅谷》"],
    };
  },
};
</script>

<style scoped>
.container,.centerdiv{
  display: flex;
  justify-content: space-around;
}
</style>

子组件(Lists.vue)

<template>
  <div class="someOne">
    <h2>{{title}}名单</h2>
    <!-- 以下操作是匿名插槽,使用者需要自定义内容,最后内容会插在这个插槽内 -->
    <!-- 如果是两个插槽的话,会将传进来的东西放两遍,多个放多遍 -->
    <slot name="center">我是一个插槽,我位于中间,当没有数据传过来的时候我会显示</slot>
    <slot name="footer">我是一个插槽,我位于下面,当没有数据传过来的时候我会显示</slot>
  </div>
</template>

<script>
export default {
  // eslint-disable-next-line vue/multi-word-component-names
  name: "Lists",
  props: ["title"],
};
</script>

<style>
.someOne{
    width: 200px;
    height: 300px;
    background-color: rgb(0, 184, 144);
    margin-top: 100px;
}
h2{
    text-align: center;
    background-color: #F96B36;
}
img{
    width: 100%;
}
video{
    width: 100%;
}
</style>

四、作用域插槽

作用域插槽,可以认为是子组件向父组件传送数据的第三种方式,可以将子组件的数据带到父组件内。
如图:目前页面上的数据定义均在子组件内,但是数据的使用却在父组件内。
作用域插槽:插槽内的数据只在本插槽范围内起作用。
在这里插入图片描述
App.vue

<template>
  <div class="container">
    <Category title="游戏">
      <template scope="atguigu">
        <ul>
          <li v-for="(g, index) in atguigu.games" :key="index">{{ g }}</li>
        </ul>
      </template>
    </Category>

    <Category title="游戏">
      <template scope="{games}">
        <ol>
          <li style="color: red" v-for="(g, index) in games" :key="index">
            {{ g }}
          </li>
        </ol>
      </template>
    </Category>

    <Category title="游戏">
      <!-- 使用的是解构语法,将对象拆开来使用 -->
      <template slot-scope="{ games, msg }">
        <h4 v-for="(g, index) in games" :key="index">{{ g }}</h4>
        <h3>{{ msg }}</h3>
      </template>
    </Category>
  </div>
</template>

<script>
import Category from "./components/Category";
export default {
  name: "App",
  components: { Category },
};
</script>

<style scoped>
.container,
.foot {
  display: flex;
  justify-content: space-around;
}
h4 {
  text-align: center;
}
</style>

Lists.vue

<template>
	<div class="category">
		<h3>{{title}}分类</h3>
		<slot :games="games" msg="hello">我是默认的一些内容</slot>
	</div>
</template>

<script>
	export default {
		// eslint-disable-next-line vue/multi-word-component-names
		name:'Category',
		props:['title'],
		data() {
			return {
				games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
			}
		},
	}
</script>

<style scoped>
	.category{
		background-color: skyblue;
		width: 200px;
		height: 300px;
	}
	h3{
		text-align: center;
		background-color: orange;
	}
	video{
		width: 100%;
	}
	img{
		width: 100%;
	}
</style>

到这里插槽的几种使用方式也就结束了,如果有更好的用法欢迎评论区留言!
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷尔。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值