vue slot插槽——vue2、vue3默认插槽、具名插槽使用


    不管是vue2还是vue3的插槽,他们都分为两种:默认插槽和具名插槽。
插槽的优点就是,只需要摆放正确插槽出口的位置(样式调整好),定义插槽内容的顺序在组件中可以随意,但是同名的插槽内容总是会覆盖上一个插槽内容(vue2中)。

  什么是默认插槽?什么是具名插槽?
  slot标签不指定name属性的时候就是默认插槽,反之就是具名插槽。在定义插槽内容的时候,所有不指定插槽名称的内容,都会被输出到默认插槽的位置,反之也是一样。

以下所有示例粘贴即用

1、vue2插槽

补充:
    vue2中插槽内容定义:在vue2.6.0之后,使用 v-slot或者语法糖#插槽名定义;在这之前使用slot="插槽名"定义。

下面关于vue2版本使用的是:vue2.7.14
在这里插入图片描述
在这里插入图片描述

1.1、默认插槽

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>Vue2 插槽</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<div id="app">
		{
   
   { message }}
		<hello-component>
			<!-- 
						下面是三种默认插槽的内容定义方式
						并且最后一个默认插槽的内容会覆盖掉上一个插槽内容
			 -->

			<!-- 默认插槽内容输出1 -> 组件中定义内容不指定插槽名称或者指定插槽名称为default,即把内容输出到默认插槽位置 -->
			<template>
				<span style="color: red">这里是默认插槽内容,字体为红色</span>
			</template>
			<!-- 默认插槽内容输出2 ->  -->
			<template v-slot:default>
				<span style="color: green">这里是默认插槽内容,字体为绿色</span>
			</template>
			<!-- 默认插槽内容输出3 ->  -->
			<template #default>
				<span style="color: yellow">这里是默认插槽内容,字体为黄色</span>
			</template>
		</hello-component>
	</div>
</body>

<!-- vue3 CDN -->
<!-- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> -->

<!-- vue2 CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>


<script type="text/javascript">

	// 先定义一个组件(就把他当成单独文件的一个组件就可以),组件里定义插槽出口
	let HelloComponent = {
      
      
		template: `
								<div>
									<div>
										<!-- 默认插槽:不指定插槽name属性的定义。这里也是插槽的内容出口(不写名字出口会带有隐含的名字“default”)==> slot name="default" -->
										<slot></slot>
									</div>
								</div>
							`
	}

var app = new Vue({
      
      
  el: '#app',
  data: {
      
      
    message: 'Hello Vue2'
  },
  // 注册组件
  components: {
      
      
  	HelloComponent
  }
})
</script>
</html>

插槽内容输出示例:最后一个插槽内容覆盖了之前所有的内容
image.png

1.2、具名插槽

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>Vue2 插槽</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<div id="app">
		{
   
   { message }}
		<hello-component>
			<!-- 
						下面是两种具名插槽的内容定义方式
						并且最后一个插槽的内容会覆盖掉上一个插槽内容
			 -->
			<!-- 注意默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确 -->
			<!-- 版本不一样插槽内容定义方式也略有不同,但是最终结果相同 -->
			<!-- 具名插槽内容输出1 -->
			<template v-slot:my-slot-name>
				<span style="color: red;">这里是具名插槽内容,字体为红色</span>
			</template>
			<!-- 具名插槽内容输出1 -->
			<template #my-slot-name>
				<span style="color: green;">这里是具名插槽内容,字体为绿色</span>
			</template>
		</hello-component>
	</div>
</body>

<!-- vue3 CDN -->
<!-- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> -->

<!-- vue2 CDN -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>


<script type="text/javascript">

	// 先定义一个组件(就把他当成单独文件的一个组件就可以),组件里定义插槽出口
	let HelloComponent = {
      
      
		template: `
								<div>
									<div>
										<!-- 具名插槽:指定了name属性, 内容出口 -->
										<slot name="my-slot-name"></slot>
									</div>
								</div>
							`
	}

var app = new Vue({
      
      
  el: '#app',
  data: {
      
      
    message: 'Hello Vue2'
  },
  // 注册组件
  components: {
      
      
  	HelloComponent
  }
})
</script>
</html>

插槽内容输出示例:最后一个插槽内容覆盖了之前所有的内容
image.png

2、vue3插槽

关于vue3中插槽内容的覆盖与vue2有所不同:vue2总是会展示最后一个插槽的内容,vue3会展示第一个_template_标签内插槽内容。具体细节可以复制下面示例自行体验。

2.1、默认插槽

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>Vue3 插槽</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<div id="app">
		{
   
   { message }}
		<hello-component>
			<!-- vue3插槽定义 -->
			<!-- 方式1:不写template标签,直接把内容写在组件内,内容默认输出到默认插槽 -->
			<span>这里是默认插槽内容,字体为黑色</span>
			<!-- 方式3:  v-slot:default定义-->
			<template v-slot:default>
				<span style="color: green;">这里是默认插槽内容,字体为绿色</span>
			</template>
			<!-- 方式2: #default 定义 -->
			<template #default>
				<span style="color: red;">这里是默认插槽内容,字体为红色</span>
			</template>
		</hello-component>
	</div>
</body>

<!-- vue3 CDN -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<!-- vue2 CDN -->
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> -->


<script type="text/javascript">

	// 先定义一个组件(就把他当成单独文件的一个组件就可以),组件里定义插槽出口
	let HelloComponent = {
      
      
		template: `
								<div>
									<div>
										<!-- 默认插槽:指定了name属性, 内容出口 -->
										<slot></slot>
									</div>
								</div>
							`
	}

	const {
      
       createApp } = Vue
  
  createApp({
      
      
    data() {
      
      
      return {
      
      
        message: 'Hello Vue3!'
      }
    }, 
    components: {
      
      
			HelloComponent
    }
  }).mount('#app')

</script>
</html>

插槽内容输出示例:展示了第一个template标签的插槽内容
image.png

2.2、具名插槽

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>Vue3 插槽</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<div id="app">
		{
   
   { message }}
		<hello-component>
			<!-- vue3插槽定义 -->
			<!-- 方式2: #default 定义 -->	
			<template #my-slot-name>
				<span style="color: red;">这里是my-slot-name具名插槽内容,字体为红色</span>
			</template>
			<!-- 方式1: v-slot:my-slot-name定义-->
			<template v-slot:my-slot-name>
				<span style="color: green;">这里是my-slot-name具名插槽内容,字体为绿色</span>
			</template>			
			<template v-slot:my-slot-name2>
				<span style="color: blue;">这里是my-slot-name2具名插槽内容,字体为蓝色</span>
			</template>
		</hello-component>
	</div>
</body>

<!-- vue3 CDN -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<!-- vue2 CDN -->
<!-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> -->


<script type="text/javascript">

	// 先定义一个组件(就把他当成单独文件的一个组件就可以),组件里定义插槽出口
	let HelloComponent = {
      
      
		template: `
								<div>
									<div>
										<!-- 具名插槽:指定了name属性, 内容出口 -->
										<slot name="my-slot-name2"></slot>
									</div>
									<div>
										<!-- 具名插槽:指定了name属性, 内容出口 -->
										<slot name="my-slot-name"></slot>
									</div>
								</div>
							`
	}

	const {
      
       createApp } = Vue
  
  createApp({
      
      
    data() {
      
      
      return {
      
      
        message: 'Hello Vue3!'
      }
    }, 
    components: {
      
      
			HelloComponent
    }
  }).mount('#app')

</script>
</html>

插槽内容输出示例:展示了第一个template标签的插槽内容
image.png

总结

  1. vue2、vue3插槽都能使用v-slot:xxx或者其缩写#xxx来定义内容;
  2. 经以上测试发现:vue2的插槽内容总是最后一个生效、vue3是第一个定义的template标签插槽内容生效;
  3. 经以上测试发现:在纯原生html中的测试示例中,vue2、vue3的具名插槽命名方式均为abc或者a-b-c的命名方式,大写不可以(ABC)、大小写混合(aBC)不可以(但是在脚手架中并没有发现这个问题);
  4. vue2、vue3插槽内容输出位置都和内容定义位置无关,所以说只要把插槽样式表写好,插槽哪里需要哪里放;

附 - 作用域插槽(以vue3示例)

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>Vue3 插槽</title>
</head>
<body>
	<div id="app">
		{
   
   { message }}
		<hello-component>
			<!-- vue3插槽定义 -->
			<!-- scope:是我指定的作用域,这个作用域是插槽的作用域,可以获取插槽上除name属性外的其他自定义属性,来获取到插槽上的数据 -->
			<!-- 在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽 -->
			<template #my-slot-name="scope">
				<!-- 下面这些值将会展示到插槽出口位置 -->
				<span style="color: red;">{
   
   { scope }}</span><br>
				<span style="color: red;">{
   
   { scope.slotMessage }}</span><br>
				<span style="color: red;">{
   
   { scope.slotMessage2 }}</span><br>
			</template>
		</hello-component>
	</div>
</body>

<!-- vue3 CDN -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>


<script type="text/javascript">

	// 先定义一个组件(就把他当成单独文件的一个组件就可以),组件里定义插槽出口
	let HelloComponent = {
      
      
		template: `
								<div>
									<div>
										<!-- 具名插槽:指定了name属性, 内容出口 -->
										<slot name="my-slot-name" slotMessage="Hello slot" slotMessage2="Hello slot2"></slot>
									</div>
								</div>
							`
	}

	const {
      
       createApp } = Vue
  
  createApp({
      
      
    data() {
      
      
      return {
      
      
        message: 'Hello Vue3!'
      }
    }, 
    components: {
      
      
			HelloComponent
    }
  }).mount('#app')

</script>
</html>

猜你喜欢

转载自blog.csdn.net/dongzi_yu/article/details/129751748