vite-uni-dev-tool
Version:
vite-uni-dev-tool, debug, uni-app, 一处编写,到处调试
238 lines (223 loc) • 7.66 kB
text/typescript
import { isArray, isObject, isString, isSymbol } from '../../utils';
import type { ComponentInternalInstance, VNode } from 'vue';
// 类型守卫函数,检查是否为VNode类型
function isVNode(child: any): child is VNode {
return child != null && typeof child === 'object' && 'type' in child;
}
// 类型守卫函数,检查是否为包含component属性的对象
function hasComponentProperty(
child: any,
): child is VNode & { component?: ComponentInternalInstance } {
return isVNode(child) && 'component' in child;
}
// 类型守卫函数,检查type是否具有name和__name属性
function hasNameProperty(
type: any,
): type is { name?: string; __name?: string } {
return isObject(type) && ('name' in type || '__name' in type);
}
// 类型守卫函数,检查是否为Symbol类型且具有description属性
function isSymbolWithDescription(
value: any,
): value is Symbol & { description?: string } {
return typeof value === 'symbol';
}
/**
* 简化的树节点类型
*/
interface SimpleTreeNode {
type: string;
uid?: number;
children?: SimpleTreeNode[];
content?: string;
}
/**
* 简化树结构,只保留在ComponentInternalInstance中必要的属性
* @param vNode - Vue组件内部实例
* @returns 简化的树结构
*/
export function simpleTree(vNode?: any): SimpleTreeNode | null {
if (!vNode) {
return null;
}
// 确保只使用必需的属性
const simplifiedInstance: InstanceTree.SimplifiedComponentInternalInstance = {
type: vNode.type,
subTree: vNode.subTree,
uid: vNode.uid,
...(vNode.component && { component: vNode.component }),
...(vNode.children && { children: vNode.children }),
};
const children: SimpleTreeNode[] = [];
// 获取子节点
if (simplifiedInstance.subTree) {
// 处理 subTree 的 children
if ('data-dev-tool' in (simplifiedInstance.subTree.props ?? {})) {
// 排除dev tool 节点
} else if (
simplifiedInstance.subTree.children &&
isArray(simplifiedInstance.subTree.children)
) {
for (const child of simplifiedInstance.subTree.children) {
if (hasComponentProperty(child) && child?.component) {
// 子组件实例
const childTree = simpleTree(child.component);
if (childTree) {
children.push(childTree);
}
} else if (isVNode(child) && child?.type) {
if (isObject(child.type)) {
children.push({
type: hasNameProperty(child.type)
? child.type.name || child.type.__name || 'Anonymous'
: 'Anonymous',
children: child.children ? getSimpleChildrenFromVNode(child) : [],
});
} else if (isString(child.type)) {
children.push({
type: child.type,
children: child.children ? getSimpleChildrenFromVNode(child) : [],
});
} else {
if (
child.type &&
isSymbolWithDescription(child.type) &&
(child.type.description === 'v-fgt' ||
child.type.description === 'v-txt' ||
child.type.description === 'v-cmt')
) {
// 跳过虚拟节点
// 跳过当前层直接处理下一层
const fragmentChildren = getSimpleChildrenFromVNode(child);
children.push(...fragmentChildren);
}
}
} else if (isString(child)) {
// 处理字符串类型的子节点
children.push({
type: 'text',
content: child,
});
}
}
}
// 如果 subTree 是组件实例
else if (simplifiedInstance.subTree.component) {
const childTree = simpleTree(simplifiedInstance.subTree.component);
if (childTree) {
children.push(childTree);
}
}
}
// 构建当前节点
let nodeInfo: SimpleTreeNode;
if (isObject(simplifiedInstance.type)) {
nodeInfo = {
type: hasNameProperty(simplifiedInstance.type)
? simplifiedInstance.type.name ||
simplifiedInstance.type.__name ||
'Component'
: 'Component',
uid: simplifiedInstance.uid, // 添加唯一标识
children,
};
} else if (isString(simplifiedInstance.type)) {
nodeInfo = {
type: simplifiedInstance.type,
uid: simplifiedInstance.uid, // 添加唯一标识
children,
};
} else {
nodeInfo = {
type: 'template',
uid: simplifiedInstance.uid,
children,
};
}
return nodeInfo;
}
/**
* 从 VNode 获取简化的子节点
*/
function getSimpleChildrenFromVNode(vnode: any): SimpleTreeNode[] {
const children: SimpleTreeNode[] = [];
if (vnode.children) {
if (isArray(vnode.children)) {
for (const child of vnode.children) {
if (hasComponentProperty(child) && child?.component) {
// 优先处理组件实例
const childTree = simpleTree(child.component);
if (childTree) {
children.push(childTree);
}
} else if (isVNode(child) && child?.type) {
if (isObject(child.type)) {
children.push({
type: hasNameProperty(child.type)
? child.type?.name || child.type?.__name || 'Anonymous'
: 'Anonymous',
children: child.children ? getSimpleChildrenFromVNode(child) : [],
});
} else if (isString(child.type)) {
children.push({
type: child.type,
children: child.children ? getSimpleChildrenFromVNode(child) : [],
});
} else {
// 处理文本节点或其他类型节点
if (
child.type &&
isSymbolWithDescription(child.type) &&
(child.type.description === 'v-fgt' ||
child.type.description === 'v-txt' ||
child.type.description === 'v-cmt')
) {
// 跳过当前层直接处理下一层
const fragmentChildren = getSimpleChildrenFromVNode(child);
children.push(...fragmentChildren);
} else {
// 处理其他类型的节点
children.push({
type:
typeof child.type !== 'object'
? isSymbolWithDescription(child.type)
? child.type.description || 'symbol-node'
: String(child.type)
: 'unknown-node',
children: child.children
? getSimpleChildrenFromVNode(child)
: [],
});
}
}
} else if (isString(child)) {
// 处理字符串类型的子节点
children.push({
type: 'text',
content: child,
});
}
}
} else if (isString(vnode.children)) {
// 处理文本节点
// 过滤空的 v-txt 节点
if (
isSymbolWithDescription(vnode.type) &&
vnode.type?.description === 'v-txt'
) {
// 文本节点
children.push({
type: '',
content: vnode.children,
});
} else {
// 注释节点
children.push({
type: vnode.type?.description || '',
content: vnode.children,
});
}
}
}
return children;
}