> 文章列表 > vue3插槽的使用

vue3插槽的使用

vue3插槽的使用

插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。

1.插槽基本使用

子组件SlotComponent.vue
<template><div class="child-box"><p>我是子组件</p><!-- 插槽 --><slot></slot></div></template>
<script setup lang="ts">
</script>
父组件
<template><div class="demo1"><h1>我是父组建</h1><SlotComponent></SlotComponent></div>
</template><script setup lang="ts">
import SlotComponent from "./component/SlotComponent.vue";
</script>
输出结果:

vue3插槽的使用

2.插槽默认内容

<template><div class="child-box"><p>我是子组件</p><!-- 插槽 --><slot><p>我是默认内容</p></slot></div>
</template>
<script setup lang="ts"></script>
输出结果:

vue3插槽的使用

3.具名插槽

子组件SlotComponent.vue
<template><div class="child-box"><p>我是子组件</p><header><slot name="header"></slot></header><main><slot></slot></main><footer><slot name="footer"></slot></footer></div>
</template>
<script setup lang="ts"></script>

上段代码中我们添加了 3 个 slot 插槽,并且给其中两个 slot 标签添加了一个 name 属性,也就是每个插槽的名字。需要注意的是,上段代码中有一个插槽我们没有添加 name 属性,这个时候 Vue 会隐式的将这个插槽命名为“default”,

父组件
<template><div class="demo1"><h1>我是父组建</h1><SlotComponent><template #header><div>我是 header{{ message }}</div></template><template #default><div>我没有名字{{ message }}</div><div>我没有名字{{ message }}</div><div>我没有名字{{ message }}</div></template><template #footer><div>我是 footer{{ message }}</div></template></SlotComponent></div>
</template>
<script setup lang="ts">
import SlotComponent from "./component/SlotComponent.vue";
const message = ref("---我是父组建中的数据");
</script>
输出结果:

vue3插槽的使用

4.简写

原写法
<template v-slot:footer></template>
简写
<template #footer></template>

默认插槽与具名插槽混用

当一个子组件中既有具名插槽,又有默认插槽时,该如何渲染呢?

前面我们说默认插槽会被隐式的命名为 default,所以我们传入内容时可以将插槽名字改为 defalut 即可。

子组件SlotComponent.vue
<template><div class="child-box"><p>我是子组件</p><header><slot name="header"></slot></header><main><slot></slot></main><footer><slot name="footer"></slot></footer></div>
</template>
<script setup lang="ts"></script>
父组件
<template><div class="demo1"><h1>我是父组建</h1><SlotComponent><template #header><div>我是 header{{ message }}</div></template><template #default><div>我没有名字{{ message }}</div><div>我没有名字{{ message }}</div><div>我没有名字{{ message }}</div></template><template #footer><div>我是 footer{{ message }}</div></template></SlotComponent></div>
</template>
<script setup lang="ts">
import SlotComponent from "./component/SlotComponent.vue";
const message = ref("---我是父组建中的数据");
</script>
输出结果:

vue3插槽的使用

5.插槽作用域问题

上段代码中 message 是我们在父组件中定义的数据,但是在我们的子组件SlotComponent 中渲染了出来,说明子组件中的插槽是可以访问到父组件中的数据作用域的,但是反过来是不行的,因为我们无法通过插槽拿到子组件的数据。

- 总结:
  • 插槽内容可以访问到父组件的数据作用域,就好比上述中的 message 是父组件的。
  • 插槽内容无法访问到子组件的数据,就好比上述 App.vue 中的插槽内容拿不到子组件 child 的数据。

6.作用域插槽

前一节我们说父组件中的插槽内容是无法访问到子组件中的数据的,但是,万一我们有需求就是需要在插槽内容中获取子组件数据怎么办呢?

6.1默认插槽作用域传值

子组件SlotComponent.vue
<template><div class="child-box"><p>我是子组件</p><slot text="我是子组件" :count="1"></slot></div>
</template>
<script setup lang="ts"></script>
父组件
<template><div class="demo1"><h1>我是父组建</h1><SlotComponent v-slot="slotProps"><div>{{ slotProps.text }}---{{ slotProps.count }}</div></SlotComponent></div>
</template>
<script setup lang="ts">
import SlotComponent from "./component/SlotComponent.vue";
</script>
输出结果:

vue3插槽的使用
上段代码中我们在子组件中 slot 标签上添加了一些自定义属性,属性值就是我们想要传递给父组件的一些内容。在父组件 中通过 v-slot="slotProps"等形式接收子组件传过来的数据,slotProps 的名字是可以任意取的,它是一个对象,包含了所有传递过来的数据。

需要注意的是,子组件传递过来的数据只能在子组件这个标签内使用。

父组件解构写法:
<template><div class="demo1"><h1>我是父组建</h1><SlotComponent v-slot="{ text, count }"><div>{{ text }}---{{ count }}</div></SlotComponent></div>
</template>
<script setup lang="ts">
import SlotComponent from "./component/SlotComponent.vue";
</script>

6.2具名插槽作用域传值

子组件SlotComponent.vue
<template><div class="child-box"><p>我是子组件</p><slot name="header" text="我是子组件的" :count="1"></slot></div>
</template>
<script setup lang="ts"></script>
父组件
<template><div class="demo1"><h1>我是父组建</h1><SlotComponent><template #header="{ text, count }"><div>{{ text }}---{{ count }}</div></template></SlotComponent></div>
</template>
<script setup lang="ts">
import SlotComponent from "./component/SlotComponent.vue";
</script>

上段代码中我们给 slot 添加了一个 name,在父组件中接收数据的时候不在采用 v-slot=““形式了,而是直接再插槽内容上采用#header=”“形式,当时这是简写形式,你也可以写为:v-slot:header=””

6.tsx中插槽的使用

子组件
<script lang="tsx">import { defineComponent} from 'vue';export default defineComponent({setup(props, context) {const {slots}=contextreturn () => (<div>默认插槽: {slots.default && slots.default()}</div>);},});
</script>
<style scoped></style>
父组建写法一
<script lang="tsx">import { defineComponent } from 'vue';import Child from './component/child.vue'export default defineComponent({setup() {const text = ref("欢迎");return () => (<div style="color: red" class="my-test"><h1 v-text={text.value}></h1><p>333</p><Child v-slots={{default: () => '默认的内容是'}}/></div>);},});
</script>
<style scoped></style>
父组建写法二
<script lang="tsx">import { defineComponent } from 'vue';import Child from './component/child.vue'export default defineComponent({setup() {const text = ref("欢迎");return () => (<div style="color: red" class="my-test"><h1 v-text={text.value}></h1><p>333</p><Child>{{default: () => '默认的内容是'}}</Child></div>);},});
</script>
<style scoped></style>
输出结果:

vue3插槽的使用