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;
|