1:如何不使用 template 模板语法 设置插槽 slot
用 defineComponent :
const Container= defineComponent({
setup(){
defineSlots<{
title:String,
default:String
}>()
},// 这段的作用是定义slot的类型,可以不用写
render() {
return h("div", [
h("slot", this.$slots.title&&this.$slots.title()||'默认title插槽;'),
h("slot", this.$slots.default&&this.$slots.default()||'默认default插槽\n'),
]);
},
});
如果用的是template 加 setup语法糖 可以这么写
<script lang="ts" setup>
import {h} from 'vue'
const slots=defineSlots<{
default:()=>{},
prefix:Function // 类型可以是箭头函数也可以是Function,反正肯定是一个函数,因为在实现阶段,必须是函数执行,webstorm在这不会报错,但是在后面的执行阶段只有按函数执行具名插槽才会生效
}>() // 用于定义slots的类型,在父级组件可以识别有哪些具名插槽,类型一定是函数
// 因此函数体内放入实参没有实际意义
const ComponentWrapper=h('div',[
h("slot",{name:'default'},{default:()=>slots.default()}),//类型默认是一个函数,写成slots.default,根本无法生效
h("slot",{},slots.prefix()), // 可以不用声明具名插槽的名称
])
<script>
如果问百度,百度给的写法是这样的,并不会生效,这写法是错误的,意思是一定要有slots来源和slot内容,要么是通过option挂载在组件上,要么是通过composition声明。
const Container = defineComponent({
render() {
return h("div", [
h("slot", { name: "title" }),
h("slot", { name: "default" }),
]);
},
});
2 直接使用 h 函数,渲染原生标签,在default插槽里面不能直接插入组件和标签
原生标签可以插入字符串、数组;
自定义组件可以直接插入组件;
但是如果原生标签里面要插入组件或者标签,必须套在数组里面;
如果不用强调default插槽,则可以
<script setup lang="ts">
import { defineComponent, h } from "vue";
// import ComponentFC from "./ComponentFC";
const ComponentA = h("span", {}, { default: () => "hello world" });
const ComponentB = h("span", ComponentA);
const ComponentC = h("span", {}, { default: () => ComponentA });// 无效
const ComponentD = h("span", {}, { default: () => h("a", "hello a") });// 无效
const ComponentE = h("span", {}, { default: () => [ComponentA] });
const ComponentFC= defineComponent({
render() {
return h("div", [
h("slot", this.$slots.title&&this.$slots.title()||'默认title插槽;'),
h("slot", this.$slots.default&&this.$slots.default()||'默认default插槽\n'),
]);
},
});
const ComponentF = h(
ComponentFC,
{},
{ title: () => "这是一个标题;", default: () => "这是一个内容;" }
);
const ComponentF2 = h(
ComponentFC,
{},
{
title: () => h("a", {}, { default: () => "这是第二个标题;\n" }),
default: () => h("a", {}, { default: () => "这是第二内容;\n" }),
}
);
const ComponentF3 = h(
ComponentFC,
[h("a", {}, { default: () => "这是第三个标题;\n" }),
h("a", {}, { default: () => "这是第三内容;\n" })
]
);
</script>
<template>
<div>
A:
<ComponentA />
</div>
<div>
B:
<ComponentB />
</div>
<div>
C:
<ComponentC /> // 无效
</div>
<div>
D:
<ComponentD />// 无效
</div>
<div>
E:
<ComponentE />
</div>
<div>F:<ComponentF /></div>
<div>FC:<ComponentFC/></div>
<div>F2:<ComponentF2 /></div>
<div>F3:<ComponentF3 /></div>
<div>F4:<ComponentFC>
<template v-slot:default>
<span><p>这是第四个default;</p></span>
</template>
<template v-slot:title>
<span><h2>这是第四个title</h2></span>
</template>
</ComponentFC></div>
</template>
<style scoped>
div{
display: flex;
align-items: center;
}
</style>
结果
A:
hello world
B:
hello world
C:
// 无效
D:
// 无效
E:
hello world
F:
这是一个标题;这是一个内容;
FC:
默认title插槽;默认default插槽
F2:
这是第二个标题; 这是第二内容;
F3:
默认title插槽;这是第三个标题; 这是第三内容;
F4:
这是第四个title
这是第四个default;
按照目前查到的信息来说,不能算bug,是官方对这个api的特殊设计,最操蛋的是,以上错误的写法,是不会报错的