vue3 不使用template,只使用h函数和defineComponent定义插槽slot的方法和bug

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的特殊设计,最操蛋的是,以上错误的写法,是不会报错的

  • 9
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值