深入了解 vue 中的四种槽:槽--通过槽名映射到 VNode 数组的对象
最编程
2024-07-14 12:25:33
...
一、前言
相信很多的小伙伴在日常开发当中经常使用vue的插槽,通过官方的文档
[插槽](https://v2.cn.vuejs.org/v2/guide/components-slots.html)
我们能够很轻松的学会如何在项目中使用插槽。那么你有没有深入了解在插槽中
使用的vm.$slots具体是什么呢?
二、四种插槽
-
四种插槽分别是什么
- 匿名插槽
- 具名插槽
- 动态插槽vue3.x ---->为什么强调是vue3.x?请往下看
- 作用域插槽
-
如何使用插槽
1. 匿名插槽
概念:没有具名的插槽,也称为匿名插槽。它可以在组件模板中作为组件内容的占位符
// 父组件
<div class="father-component">
<childTemp>
<p class="default">这是匿名插槽的内容</p>
</childTemp>
</div>
// 子组件
<div class="child-component">
<!-- 这是匿名插槽的内容 -->
<slot></slot>
</div>
2. 具名插槽
概念:具名插槽是指有一个名称(或者多个名称)的插槽,它们可以在组件模板中通过名称引用
// 父组件
<div class="father-component">
<childTemp>
<template #header>
<p>header: 这是具名插槽的内容</p>
</template>
<template #body>
<p>body: 这是具名插槽的内容</p>
</template>
<template #footer>
<p>footer: 这是具名插槽的内容</p>
</template>
</childTemp>
</div>
// 子组件
<div class="child-component">
<slot name="header"></slot>
<slot name="body"></slot>
<slot name="footer"></slot>
</div>
3. 动态插槽
概念:动态插槽是 Vue 中的一种特殊类型的插槽,它允许使用者根据具体的业务场景来动态地创建插槽内容
在 Vue 2.x 中,如果我们想要动态地创建插槽内容,通常是使用函数式组件来实现。但是,函数式组件的写法比较麻烦,并且不能像普通组件那样维护自己的状态和生命周期钩子。Vue 3.x 引入了动态插槽的概念,通过使用
v-slot
指令
//父组件
<div class="father-component">
<childTemp>
<!-- 动态插槽 -->
<template #[dynamicSlot]>
<p>{{ dynamicSlot }}:这是动态插槽的内容</p>
</template>
</childTemp>
</div>
setup() {
const dynamicSlot = ref("dynamicSlot");
return {
dynamicSlot
};
}
// 子组件
<script>
import { createElementVNode } from "vue";
export default {
name: "",
setup(props, { slots }) {
const slotName = slots.dynamicSlot();
// 其实这里就呼应了标题-- 插槽本身就是映射到 VNode 数组的对象
return () => {
return createElementVNode("div", null, [...slotName]);
};
}
};
</script>
4. 作用域插槽
概念:动态插槽是 Vue 中的一种特殊类型的插槽,它允许子组件将自身的数据传递到父组件中进行渲染
,通常用于构建通用的 UI 组件。作用域插槽在定义时需要使用 v-slot
指令,并接受一个参数表示插槽名称.
//父组件
<div class="father-component">
<childTemp>
<!-- 作用域插槽 -->
<template #default="props">
<p>{{ props.actionScope }}</p>
</template>
</childTemp>
</div>
// 子组件
<div class="child-component">
<!-- 作用域插槽 -->
<slot :actionScope="actionScope"></slot>
</div>
export default {
setup() {
const actionScope = ref("actionScope:这是作用域插槽的内容");
return {
actionScope
};
}
};
三、$slots具体是什么
Vue 插槽是一个
对象
。在组件实例的vm.$slots
属性中,每个插槽都表示为一个包含 VNode 的数组,因此vm.$slots
对象本身就是一个由插槽名映射到 VNode 数组的对象
举例说明
// 父组件
<div class="father-component">
<childTemp :dynamicSlot="dynamicSlot">
<!-- 匿名插槽 -->
<p class="default">这是默认插槽的内容</p>
<!-- 具名插槽 -->
<template #header>
<p>header: 这是具名插槽的内容</p>
</template>
<template #body>
<p>body: 这是具名插槽的内容</p>
</template>
<template #footer>
<p>footer: 这是具名插槽的内容</p>
</template>
</childTemp>
</div>
接下来我们在子组件中打应这个slots
export default {
name: "",
setup(props, { slots }) {
console.log("slots", slots);
}
};
打印slots出来全是父组件定义插槽生成的VNode,那么我们在子组件是不是能直接拿到VNode渲染呢?答案是肯定可以的!!!我们不妨来试一下
<template>
<div class="child-component">
<!-- <slot></slot>
<slot name="header"></slot>
<slot name="body"></slot>
<slot name="footer"></slot> -->
</div>
</template>
<script>
import { createElementVNode } from "vue";
export default {
name: "",
setup(props, { slots }) {
console.log("slots", slots);
const _default = slots.default();
const _header = slots.header();
const _body = slots.body();
const _footer = slots.footer();
return () => {
return createElementVNode("div", null, [..._default, ..._header, ..._body, ..._footer]);
};
}
};
</script>
看到这里相信你不但会使用插槽,还对插槽有更加深入的了解。
上一篇: Reference