riku
2025-09-20 0796eebe3520fafb0ac5d36ee584af81506d7e9c
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { cloneVNode, Comment, defineComponent, Fragment, h, Text, VNode } from 'vue';
 
/**
 * 对于文本或SVG,需要用span包裹一下
 * @param s
 */
const wrapTextContent = (s: string | VNode): VNode => {
  return h('span', null, s);
};
 
/**
 * 判断是否为Object
 * @param val
 */
const isObject = (val: any) => val !== null && typeof val === 'object';
 
/**
 * 找出第一个合法的子元素
 * @param node
 */
const findFirstLegitChild = (node: VNode[] | undefined): VNode | null => {
  if (!node) return null;
  for (const child of node) {
    if (isObject(child)) {
      switch (child.type) {
        case Comment:
          continue;
        case Text:
        case 'svg':
          return wrapTextContent(child);
        case Fragment:
          return findFirstLegitChild(child.children as VNode[]);
        default:
          return child;
      }
    }
    return wrapTextContent(child);
  }
  return null;
};
 
const NAME = 'SlotEvents';
 
const SlotEvents = defineComponent({
  name: NAME,
  setup(_, { slots, attrs }) {
    return () => {
      const defaultSlot = slots.default?.(attrs);
      if (!defaultSlot) return null;
      if (defaultSlot.length > 1) {
        console.warn(`${NAME}: 只需要一个子元素`);
        return null;
      }
      const firstLegitChild = findFirstLegitChild(defaultSlot);
      if (!firstLegitChild) {
        console.warn(`${NAME}: 没有可用的子元素`);
        return null;
      }
      return cloneVNode(firstLegitChild, attrs);
    };
  }
});
export default SlotEvents;