程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Vue2

    • Vue简介
    • Vue 基础使用
    • Vue的基础指令
    • 过滤器(Filters)
    • 侦听器(Watch)
    • 计算属性(computed)
    • vue-cli
    • vue.config.js配置
    • Vue组件
    • 生命周期和数据共享
    • Vue 组件实例与数据代理 (this)
    • $refs 引用
    • 动态组件
    • 插槽 (Slots)
      • 1. 什么是插槽
      • 2. 体验插槽的基础用法
      • 3. 没有预留插槽的内容会被丢弃
      • 4. 后备内容 (默认插槽)
      • 5. 具名插槽 (v-slot)
        • 5-1 子组件中定义具名插槽
        • 5-2 父组件中向具名插槽提供内容
        • 6. 具名插槽的简写形式
      • 8. 作用域插槽
        • 8-1 子组件中定义作用域插槽
        • 8-2 父组件中使用作用域插槽
        • 8-3 使用解构赋值简化数据的接收过程
        • 8-4 具名作用域插槽
        • 8-5 具名作用域插槽的简写形式
    • 混入 (Mixin)
    • 自定义指令 (directives)
    • 插件 (Plugins)
    • 初识Vue-router
    • Vue-router的常见用法
  • Vue3

  • vue3 + TS 项目集成

  • Vue全家桶
  • Vue2
scholar
2024-07-31
目录

插槽 (Slots)

# 插槽 (Slots)

# 1. 什么是插槽

插槽(Slot)是 Vue 提供的一种技术,允许开发者在封装组件时,预留出可由组件使用者填充的内容区域。可以把插槽看作是组件封装期间,为用户预留的内容占位符。

image-20240731035322391

# 2. 体验插槽的基础用法

在封装组件时,可以通过 <slot> 元素定义插槽,从而为用户预留内容占位符。

image-20240731040000979

子组件





 









<!-- ChildComponent.vue -->
<template>
  <div>
    <h2>子组件</h2>
    <slot></slot> <!-- 定义插槽 -->
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13

父组件





 
 
 













<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <p>这是插入到子组件中的内容</p>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在这个示例中,父组件 ParentComponent 使用了子组件 ChildComponent,并向子组件的插槽中传递了一段 <p> 标签内容。渲染后的结果会在子组件的插槽位置显示父组件传递的内容。

# 3. 没有预留插槽的内容会被丢弃

如果在封装组件时没有预留任何 <slot> 插槽,则用户提供的任何自定义内容都会被丢弃。

image-20240731044758094

子组件




 









<!-- ChildComponent.vue -->
<template>
  <div>
    <h2>子组件(没有插槽)</h2>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12

父组件





 
 
 













<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <NoSlotComponent>
      <p>这个内容将会被丢弃,因为子组件没有定义插槽</p>
    </NoSlotComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在这个示例中,父组件向 NoSlotComponent 传递的 <p> 标签内容将会被丢弃,因为子组件 NoSlotComponent 没有定义任何插槽。

# 4. 后备内容 (默认插槽)

封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效。

image-20240731053055295

子组件





 









<!-- ChildComponent.vue -->
<template>
  <div>
    <h2>子组件(带默认插槽内容)</h2>
    <slot>这是默认内容,如果没有插入内容,则显示这段文字</slot>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13

父组件





 
 
 













<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <!-- 这里没有插入内容,子组件会显示默认内容 -->
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

在这个示例中,如果父组件没有向子组件 DefaultSlotComponent 的插槽中插入内容,则子组件会显示插槽中的默认内容 “这是默认内容,如果没有插入内容,则显示这段文字”。

# 5. 具名插槽 (v-slot)

在组件封装过程中,如果需要预留多个插槽,可以为每个 <slot> 插槽指定一个具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。具名插槽允许开发者更灵活地分配内容到不同的插槽位置。

image-20240731045803196

提示

v-slot指令用于在父组件中绑定具名插槽的名称,并且v-slot 指令只能用于 <template> 标签上。

# 5-1 子组件中定义具名插槽

子组件





 

 

 









<!-- ChildComponent.vue -->
<template>
  <div>
    <h2>子组件</h2>
    <slot name="header"></slot> <!-- 定义名为 header 的插槽 -->
      
    <slot></slot> <!-- 定义一个默认插槽 -->
      
    <slot name="footer"></slot> <!-- 定义名为 footer 的插槽 -->
  </div>
</template>

<script>
export default {
  name: 'ChildComponent'
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 5-2 父组件中向具名插槽提供内容

在父组件中使用 <template> 标签并结合 v-slot 指令向具名插槽传递内容。需要注意的是,v-slot 指令只能用于 <template> 标签上。

父组件






 
 
 

 

 
 
 














<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <template v-slot:header>
        <p>这是传递给 header 插槽的内容</p>
      </template>
        
      <p>这是传递给默认插槽的内容</p>
        
      <template v-slot:footer>
        <p>这是传递给 footer 插槽的内容</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

在这个示例中,父组件 ParentComponent 使用了子组件 ChildComponent,并向具名插槽 header 和 footer 传递了不同的内容,同时也向默认插槽传递了内容。

# 6. 具名插槽的简写形式

为了简化代码,Vue 提供了 v-slot 指令的简写形式。可以使用 # 代替 v-slot:,例如 v-slot:header 可以简写为 #header。

父组件






 
 
 

 

 
 
 














<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <template #header>
        <p>这是传递给 header 插槽的内容</p>
      </template>
        
      <p>这是传递给默认插槽的内容</p>
        
      <template #footer>
        <p>这是传递给 footer 插槽的内容</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

在这个示例中,使用了 #header 和 #footer 来简写 v-slot:header 和 v-slot:footer,使得代码更简洁。

通过使用具名插槽,开发者可以在一个组件中定义多个内容占位符,并且可以灵活地控制不同内容的显示位置。这使得组件的复用性和灵活性大大提高。

# 8. 作用域插槽

在 Vue 组件开发中,可以通过定义作用域插槽(Scoped Slots)来实现组件之间的数据共享。作用域插槽允许子组件将数据传递给父组件,从而使父组件能够动态地渲染内容。

image-20240731052031469

# 8-1 子组件中定义作用域插槽

在子组件中,可以通过 <slot> 元素结合 v-bind 指令来定义作用域插槽,并将数据绑定到插槽上。

子组件






 








 












<!-- ChildComponent.vue -->
<template>
  <div>
    <h2>子组件</h2>
    <!-- 定义一个作用域插槽,并向其绑定 props 数据 -->
    <slot :user="user"></slot>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  data() {
    return {
      user: { name: 'John Doe', age: 25 } // 定义一些数据
    };
  }
};
</script>

<style scoped>
/* 子组件的样式 */
h2 {
  color: blue;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

在这个示例中,子组件 ChildComponent 定义了一个作用域插槽 <slot :user="user"></slot>,并向其绑定了 user 数据。通过这种方式,子组件可以将 user 数据传递给使用该组件的父组件。

# 8-2 父组件中使用作用域插槽

在父组件中,可以通过 <template> 元素结合 v-slot 指令接收作用域插槽提供的数据,并在插槽中使用这些数据。

父组件








 
 
 
 





















<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <!-- 使用 v-slot 指令接收作用域插槽提供的数据 -->
      <!-- v-slot:default 是固定写法,表示接收子组件默认插槽的数据 -->
      <template v-slot:default="slotProps">
        <p>用户名称:{{ slotProps.user.name }}</p>
        <p>用户年龄:{{ slotProps.user.age }}</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

<style scoped>
/* 父组件的样式 */
h1 {
  color: red;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

在这个示例中,父组件 ParentComponent 使用 <template v-slot:default="slotProps"> 接收子组件传递的 user 数据。这里的 v-slot:default 是 Vue 的固定写法,用于接收子组件默认插槽的数据。slotProps 是一个对象,包含了子组件传递的数据。

提示

如果要接收具名插槽的数据,可以使用 v-slot:name 的形式,其中 name 是插槽的名称,还可以简写成 #name 的形式。

# 8-3 使用解构赋值简化数据的接收过程

为了简化代码,可以使用解构赋值直接从 slotProps 对象中提取所需的数据。这种方式可以使代码更加简洁和易读。

父组件








 
 
 
 





















<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <!-- 使用解构赋值简化数据的接收过程 -->
      <!-- v-slot:default 是固定写法,解构赋值可以直接提取 user 数据 -->
      <template v-slot:default="{ user }">
        <p>用户名称:{{ user.name }}</p>
        <p>用户年龄:{{ user.age }}</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

<style scoped>
/* 父组件的样式 */
h1 {
  color: red;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

在这个示例中,父组件 ParentComponent 使用解构赋值直接从 slotProps 对象中提取 user 数据。通过这种方式,父组件可以更加方便地访问子组件传递的数据。

# 8-4 具名作用域插槽

如果子组件定义了具名插槽,父组件可以使用 v-slot:name 的形式接收这些插槽的数据。

子组件






 
 








 












<!-- ChildComponent.vue -->
<template>
  <div>
    <h2>子组件</h2>
    <!-- 定义具名插槽 -->
    <slot name="header" :user="user"></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  data() {
    return {
      user: { name: 'John Doe', age: 25 } // 定义一些数据
    };
  }
};
</script>

<style scoped>
/* 子组件的样式 */
h2 {
  color: blue;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

父组件







 
 
 

 
 
 





















<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <!-- 使用 v-slot:header 指令接收具名插槽的数据 -->
      <template v-slot:header="{ user }">
        <p>用户名称:{{ user.name }}</p>
      </template>

      <template v-slot:footer>
        <p>这是底部内容</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

<style scoped>
/* 父组件的样式 */
h1 {
  color: red;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

在这个示例中,父组件 ParentComponent 使用 <template v-slot:header="{ user }"> 接收子组件具名插槽 header 传递的数据,并使用 <template v-slot:footer> 提供子组件具名插槽 footer 的内容。

# 8-5 具名作用域插槽的简写形式

跟 v-on 和 v-bind 一样,v-slot 也有缩写形式,即把参数之前的所有内容(v-slot:)替换为字符 #。例如 v-slot:header 可以被简写为 #header。

父组件(简写形式)







 
 
 

 
 
 





















<!-- ParentComponent.vue -->
<template>
  <div>
    <h1>父组件</h1>
    <ChildComponent>
      <!-- 使用 v-slot:header 的简写形式接收具名插槽的数据 -->
      <template #header="{ user }">
        <p>用户名称:{{ user.name }}</p>
      </template>

      <template #footer>
        <p>这是底部内容</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  }
};
</script>

<style scoped>
/* 父组件的样式 */
h1 {
  color: red;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

在这个示例中,父组件 ParentComponent 使用 #header="{ user }" 接收子组件具名插槽 header 传递的数据,使用 #footer 提供子组件具名插槽 footer 的内容。

总结

  • 定义作用域插槽:在子组件中定义 <slot> 插槽时,可以使用 v-bind 绑定数据。这些数据将作为 props 传递给父组件中的插槽。
  • 使用作用域插槽:在父组件中使用 <template> 元素结合 v-slot 指令接收子组件传递的数据。v-slot:default 是 Vue 的固定写法,用于接收子组件默认插槽的数据。如果要接收具名插槽的数据,可以使用 v-slot:name 的形式,其中 name 是插槽的名称。
  • 解构插槽 Prop:为了简化代码,可以使用解构赋值直接从数据对象中提取所需的数据。
编辑此页 (opens new window)
上次更新: 2025/01/30, 23:55:43
动态组件
混入 (Mixin)

← 动态组件 混入 (Mixin)→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式