Skip to content

Commit 00170ba

Browse files
committed
feat: new visitComponentTree hook called for each node in the tree
1 parent a7d7838 commit 00170ba

File tree

6 files changed

+54
-26
lines changed

6 files changed

+54
-26
lines changed

packages/api/src/api/hooks.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const enum Hooks {
88
GET_APP_ROOT_INSTANCE = 'getAppRootInstance',
99
REGISTER_APPLICATION = 'registerApplication',
1010
WALK_COMPONENT_TREE = 'walkComponentTree',
11+
VISIT_COMPONENT_TREE = 'visitComponentTree',
1112
WALK_COMPONENT_PARENTS = 'walkComponentParents',
1213
INSPECT_COMPONENT = 'inspectComponent',
1314
GET_COMPONENT_BOUNDS = 'getComponentBounds',
@@ -51,6 +52,11 @@ export type HookPayloads = {
5152
maxDepth: number
5253
filter: string
5354
}
55+
[Hooks.VISIT_COMPONENT_TREE]: {
56+
componentInstance: ComponentInstance
57+
treeNode: ComponentTreeNode
58+
filter: string
59+
}
5460
[Hooks.WALK_COMPONENT_PARENTS]: {
5561
componentInstance: ComponentInstance
5662
parentInstances: ComponentInstance[]
@@ -126,6 +132,7 @@ export interface Hookable<TContext> {
126132
getAppRootInstance (handler: HookHandler<HookPayloads[Hooks.GET_APP_ROOT_INSTANCE], TContext>)
127133
registerApplication (handler: HookHandler<HookPayloads[Hooks.REGISTER_APPLICATION], TContext>)
128134
walkComponentTree (handler: HookHandler<HookPayloads[Hooks.WALK_COMPONENT_TREE], TContext>)
135+
visitComponentTree (handler: HookHandler<HookPayloads[Hooks.VISIT_COMPONENT_TREE], TContext>)
129136
walkComponentParents (handler: HookHandler<HookPayloads[Hooks.WALK_COMPONENT_PARENTS], TContext>)
130137
inspectComponent (handler: HookHandler<HookPayloads[Hooks.INSPECT_COMPONENT], TContext>)
131138
getComponentBounds (handler: HookHandler<HookPayloads[Hooks.GET_COMPONENT_BOUNDS], TContext>)

packages/app-backend-api/src/api.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
TimelineEventOptions,
1010
CustomInspectorOptions,
1111
EditStatePayload,
12-
WithId
12+
WithId,
13+
ComponentTreeNode
1314
} from '@vue/devtools-api'
1415
import { DevtoolsHookable } from './hooks'
1516
import { BackendContext } from './backend-context'
@@ -84,6 +85,15 @@ export class DevtoolsApi {
8485
return payload.componentTreeData
8586
}
8687

88+
async visitComponentTree (instance: ComponentInstance, treeNode: ComponentTreeNode, filter: string = null) {
89+
const payload = await this.callHook(Hooks.VISIT_COMPONENT_TREE, {
90+
componentInstance: instance,
91+
treeNode,
92+
filter
93+
})
94+
return payload.treeNode
95+
}
96+
8797
async walkComponentParents (instance: ComponentInstance) {
8898
const payload = await this.callHook(Hooks.WALK_COMPONENT_PARENTS, {
8999
componentInstance: instance,

packages/app-backend-api/src/hooks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ export class DevtoolsHookable implements Hookable<BackendContext> {
6161
this.hook(Hooks.WALK_COMPONENT_TREE, handler)
6262
}
6363

64+
visitComponentTree (handler: Handler<HookPayloads[Hooks.VISIT_COMPONENT_TREE]>) {
65+
this.hook(Hooks.VISIT_COMPONENT_TREE, handler)
66+
}
67+
6468
walkComponentParents (handler: Handler<HookPayloads[Hooks.WALK_COMPONENT_PARENTS]>) {
6569
this.hook(Hooks.WALK_COMPONENT_PARENTS, handler)
6670
}

packages/app-backend-vue3/src/components/tree.ts

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class ComponentWalker {
1818
this.componentFilter = new ComponentFilter(filter)
1919
}
2020

21-
getComponentTree (instance: any) {
21+
getComponentTree (instance: any): Promise<ComponentTreeNode[]> {
2222
this.captureIds = new Map()
2323
return this.findQualifiedChildren(instance, 0)
2424
}
@@ -43,9 +43,9 @@ export class ComponentWalker {
4343
* @param {Vue|Vnode} instance
4444
* @return {Vue|Array}
4545
*/
46-
private findQualifiedChildren (instance: any, depth: number) {
46+
private async findQualifiedChildren (instance: any, depth: number): Promise<ComponentTreeNode[]> {
4747
if (this.componentFilter.isQualified(instance)) {
48-
return [this.capture(instance, null, depth)]
48+
return [await this.capture(instance, null, depth)]
4949
} else if (instance.subTree) {
5050
// TODO functional components
5151
return this.findQualifiedChildrenFromList(this.getInternalInstanceChildren(instance.subTree), depth)
@@ -63,12 +63,14 @@ export class ComponentWalker {
6363
* @param {Array} instances
6464
* @return {Array}
6565
*/
66-
private findQualifiedChildrenFromList (instances, depth: number) {
66+
private async findQualifiedChildrenFromList (instances, depth: number): Promise<ComponentTreeNode[]> {
6767
instances = instances
6868
.filter(child => !isBeingDestroyed(child))
69-
return !this.componentFilter.filter
70-
? instances.map((child, index, list) => this.capture(child, list, depth))
71-
: Array.prototype.concat.apply([], instances.map(i => this.findQualifiedChildren(i, depth)))
69+
if (!this.componentFilter.filter) {
70+
return Promise.all(instances.map((child, index, list) => this.capture(child, list, depth)))
71+
} else {
72+
return Array.prototype.concat.apply([], await Promise.all(instances.map(i => this.findQualifiedChildren(i, depth))))
73+
}
7274
}
7375

7476
/**
@@ -119,15 +121,15 @@ export class ComponentWalker {
119121
* @param {Vue} instance
120122
* @return {Object}
121123
*/
122-
private capture (instance: any, list: any[], depth: number): ComponentTreeNode {
124+
private async capture (instance: any, list: any[], depth: number): Promise<ComponentTreeNode> {
123125
const id = this.captureId(instance)
124126

125127
const name = getInstanceName(instance)
126128

127129
const children = this.getInternalInstanceChildren(instance.subTree)
128130
.filter(child => !isBeingDestroyed(child))
129131

130-
const ret: ComponentTreeNode = {
132+
const treeNode: ComponentTreeNode = {
131133
uid: instance.uid,
132134
id,
133135
name,
@@ -141,26 +143,26 @@ export class ComponentWalker {
141143

142144
// capture children
143145
if (depth < this.maxDepth) {
144-
ret.children = children
146+
treeNode.children = await Promise.all(children
145147
.map((child, index, list) => this.capture(child, list, depth + 1))
146-
.filter(Boolean)
148+
.filter(Boolean))
147149
}
148150

149151
// record screen position to ensure correct ordering
150152
if ((!list || list.length > 1) && !instance._inactive) {
151153
const rect = getInstanceOrVnodeRect(instance)
152-
ret.positionTop = rect ? rect.positionTop : Infinity
154+
treeNode.positionTop = rect ? rect.positionTop : Infinity
153155
}
154156

155157
if (instance.suspense) {
156-
ret.tags.push({
158+
treeNode.tags.push({
157159
label: 'suspense',
158160
backgroundColor: 0xc5c4fc,
159161
textColor: 0xffffff
160162
})
161163
}
162164

163-
return ret
165+
return this.ctx.api.visitComponentTree(instance, treeNode, this.componentFilter.filter)
164166
}
165167

166168
/**

packages/app-backend-vue3/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ export const backend: DevtoolsBackend = {
2525
}
2626
})
2727

28-
api.on.walkComponentTree((payload, ctx) => {
28+
api.on.walkComponentTree(async (payload, ctx) => {
2929
const walker = new ComponentWalker(payload.maxDepth, payload.filter, ctx)
30-
payload.componentTreeData = walker.getComponentTree(payload.componentInstance)
30+
payload.componentTreeData = await walker.getComponentTree(payload.componentInstance)
3131
})
3232

3333
api.on.walkComponentParents((payload, ctx) => {

packages/shell-dev-vue3/src/devtools-plugin/index.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,20 @@ export default {
2121

2222
let time = 0
2323

24-
api.on.walkComponentTree((payload, ctx) => {
25-
for (const node of payload.componentTreeData) {
26-
if (node.name === 'MyApp') {
27-
node.tags.push({
28-
label: 'root',
29-
textColor: 0x000000,
30-
backgroundColor: 0xFF984F
31-
})
32-
}
24+
api.on.visitComponentTree((payload, ctx) => {
25+
const node = payload.treeNode
26+
if (node.name === 'MyApp') {
27+
node.tags.push({
28+
label: 'root',
29+
textColor: 0x000000,
30+
backgroundColor: 0xFF984F
31+
})
32+
} else {
33+
node.tags.push({
34+
label: 'test',
35+
textColor: 0x000000,
36+
backgroundColor: 0xFF5555
37+
})
3338
}
3439
})
3540

0 commit comments

Comments
 (0)