This commit is contained in:
oneao committed 2025-09-23 17:29:46 +08:00
1 parent 9c76e2769a
commit f285ff776f
16 files changed
+884 -89

No files matched your search

@@ -0,0 +1,69 @@
import type { VNode, VNodeChild } from 'vue'
import { Fragment } from 'vue'
/**
* 判断 vnode 是否匹配目标组件
* @param vnode VNode
* @param componentType 组件对象
* @param componentName 组件名称字符串(可选)
*/
function isTargetComponent(vnode: VNode, componentType: any, componentName?: string) {
if (!vnode)
return false
if (vnode.type === componentType)
return true
if (componentName && typeof vnode.type === 'object' && (vnode.type as any).name === componentName) {
return true
}
return false
}
/**
* 递归获取指定组件的 props 和插槽函数(不执行函数 prop)
* @param nodes VNode 数组
* @param componentType 目标组件对象
* @param componentName 目标组件名称字符串(可选)
*/
export function getComponentInnerData(
nodes: VNode[],
componentType: any,
componentName?: string,
): { item: Record<string, any>, slots: Record<string, () => VNodeChild | VNodeChild[] | null> }[] {
const result: { item: Record<string, any>, slots: Record<string, () => VNodeChild | VNodeChild[] | null> }[] = []
function traverse(vnode: VNode) {
if (!vnode)
return
if (vnode.type === Fragment && Array.isArray(vnode.children)) {
vnode.children.forEach(child => traverse(child as VNode))
return
}
if (isTargetComponent(vnode, componentType, componentName)) {
const item: Record<string, any> = {}
const slots: Record<string, () => VNodeChild | VNodeChild[] | null> = {}
if (vnode.props)
Object.assign(item, vnode.props)
if (vnode.children && typeof vnode.children === 'object' && !Array.isArray(vnode.children)) {
for (const key in vnode.children) {
const slotFn = vnode.children[key]
if (typeof slotFn === 'function') {
slots[key] = slotFn as () => VNodeChild | VNodeChild[] | null
}
}
}
result.push({ item, slots })
}
if (Array.isArray(vnode.children)) {
vnode.children.forEach(child => traverse(child as VNode))
}
}
nodes.forEach(traverse)
return result
}