File size: 20,959 Bytes
4d70170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# Plugin API References

::: warning
The API is only available in Vue Devtools 6+
:::

## Plugin setup

### setupDevtoolsPlugin

Registers a devtools plugin. Describes the plugin and provides access to the devtools API.

```js
setupDevtoolsPlugin (pluginDescriptor, setupFn)
```

The plugin descriptor is an object describing the devtools plugin to the Vue devtools user.

It has the following properties:

- `id`: a unique id between all possible plugins. It's recommended to use a Reverse Domain Name notation, for example: `org.vuejs.router`, or the npm package name.
- `app`: the current application instance. The devtools is scoped to a specific application, so you have to specify on which application instance the devtools plugin is going to work.
- `label`: the label displayed to the user. It's recommended to use a user-friendly name from your plugin, for example: `'Vue Router'`. Do not put `'devtools'` or `'plugin'` in the name, since the user will be seeing this devtools plugin while using your Vue plugin already.
- `packageName` (optional): The `npm` package name associated with the devtools plugin, for example `'vue-router'`.
- `homepage` (optional): URL to your documentation.
- `logo` (optional): URL to a logo of your Vue plugin.
- `componentStateTypes` (optional): an array of custom component state section names you are going to add to the Component inspector. If you add new state to the component inspector, you should declare their sections here so the devtools can display the plugin icon.
- `disableAppScope` (optional): if set to `true`, the hooks registered with this plugin will not be scoped to the associated app. In that case, you might need to use the `app` payload property to check what the current app is inside each hook.
- `disablePluginScope` (optional): if set to `true`, the hooks registered with this plugin will not be scoped to the current plugin. In that case, you might need to use the `pluginId` payload property (depending on the hook) to check what the related plugin is inside each hook.
- `enableEarlyProxy` (optional): if set to `true`, the plugin will run even if the Vue devtools are not connected yet using a proxy of the Plugin API and a buffer queue. This is useful if you need to add timeline events before the user opens the devtools.
- `settings` (optional): an object describing the plugin settings. Learn more about plugin settings [here](./plugins-guide.md#plugin-settings).

Example:

```js
const stateType = 'routing properties'

setupDevtoolsPlugin({
  id: 'org.vuejs.router',
  app,
  label: 'Vue Router',
  packageName: 'vue-router',
  homepage: 'https://router.vuejs.org/',
  logo: 'https://vuejs.org/images/icons/favicon-96x96.png',
  componentStateTypes: [
    stateType
  ]
}, (api) => {
  // Use the API here
})
```

## Component inspector

### on.visitComponentTree

Use this hook to add tags in the component tree.

The `payload` argument:
- `app`: app instance currently active in the devtools
- `componentInstance`: the current component instance data in the tree
- `treeNode`: the tree node that will be sent to the devtools
- `filter`: the current value of the seach input above the tree in the component inspector

Example:

```js
api.on.visitComponentTree((payload) => {
  const node = payload.treeNode
  if (node.name === 'MyApp') {
    node.tags.push({
      label: 'root',
      textColor: 0x000000,
      backgroundColor: 0xFF984F
    })
  }
  else {
    node.tags.push({
      label: 'test',
      textColor: 0xFFAAAA,
      backgroundColor: 0xFFEEEE,
      tooltip: `It's a test!`
    })
  }
})
```

### on.inspectComponent

Use this hook to add new information to the state of the selected component.

The `payload` argument:
- `app`: app instance currently active in the devtools
- `componentInstance`: the current component instance data in the tree
- `instanceData`: the state that will be sent to the devtools

To add new state, you can push new fields into the `instanceData.state` array:

#### Basic field

- `type`: name of the section under which the field will appear
- `key`: name of the field
- `value`: value of the field
- `editable` (optional): boolean to enable edition

#### Custom value

By default, the devtools will display your field depending on whether it's an object, an array, etc. You can customize the field display by putting a `{ _custom: {} }` object to the value.

The `_custom` object has the following properties:

- `type`: Displays the type of the value. Examples: `'router'`, `'component'`, `'service'`...
- `display`: Text displayed instead of the value. Example: `'5 minutes'`
- `tooltip`: Tooltip when hovering the value text (`display`)
- `value`: Actual value
- `abstract`: No value is displayed. Useful for indexes. For example, `Set` objects have abstract index child fields: `0`, `1`...
- `readOnly`: mark this value has not editable
- `fields`: an object of configure immediate child fields
  - `abstract`
- `actions`: an array of buttons to add to the field
  - `icon`: material icon identifier
  - `tooltip`: button tooltip
  - `action`: function to be executed

When you add new sections with the `type` property, you should declare them in the `componentStateTypes` array in the plugin descriptor when you call the `setupDevtoolsPlugin`.

Example:

```js
api.on.inspectComponent((payload) => {
  if (payload.instanceData) {
    payload.instanceData.state.push({
      type: stateType,
      key: 'foo',
      value: 'bar'
    })
    payload.instanceData.state.push({
      type: stateType,
      key: 'time',
      value: {
        _custom: {
          type: null,
          readOnly: true,
          display: `${time}s`,
          tooltip: 'Elapsed time',
          value: time,
          actions: [
            {
              icon: 'input',
              tooltip: 'Log to console',
              action: () => console.log('current time:', time)
            }
          ]
        }
      }
    })
  }
})
```

### on.editComponentState

If you mark a field as `editable: true`, you should also use this hook to apply the new value sent by the devtools.

You have to put a condition in the callback to target only your field type:

```js
api.on.editComponentState((payload) => {
  if (payload.type === stateType) {
    // Edit logic here
  }
})
```

The `payload` argument:
- `app`: app instance currently active in the devtools
- `type`: the current field type
- `path`: an array of string that represents the property edited by the user. For example, if the user edits the `myObj.myProp.hello` property, the `path` will be `['myObj', 'myProp', 'hello']`.
- `state`: object describing the edit with those properties:
  - `value`: new value
  - `newKey`: string that is set if the key of the value changed, usually when it's in an object
  - `remove`: if `true`, the value should be removed from the object or array
- `set`: an helper function that makes it easy to apply the edit on a state object

Example:

```js
api.on.editComponentState((payload) => {
  if (payload.type === stateType) {
    payload.set(myState)
  }
})
```

Here is a full example of an editable custom component field:

```js
const myState = {
  foo: 'bar'
}

api.on.inspectComponent((payload) => {
  if (payload.instanceData) {
    payload.instanceData.state.push({
      type: stateType,
      key: 'foo',
      value: myState.foo,
      editable: true
    })
  }
})

api.on.editComponentState((payload) => {
  if (payload.type === stateType) {
    payload.set(myState)
  }
})
```

As you can see, you should use an object to hold the field value so that it can be assigned to.

### notifyComponentUpdate

If your state has changed, you can tell the devtools to refresh the selected component state with the `notifyComponentUpdate` method:

```js
setInterval(() => {
  api.notifyComponentUpdate()
}, 5000)
```

You can also pass a specific component instance:

```js
api.notifyComponentUpdate(vm)
```

## Custom inspector

Custom inspectors are useful to display debugging information about your library using an inspectable tree.

### addInspector

This function registers a new custom inspector.

The options are:

- `id`: unique custom inspector id
- `label`: label displayed in the `Inspector` sub menu
- `icon` (optional): [Material icon code](https://material.io/resources/icons/), for example `'star'`
- `treeFilterPlaceholder` (optional): placeholder of the filter input above the tree
- `stateFilterPlaceholder` (optional): placeholder of the filter input in the state inspector
- `noSelectionText` (optional): text displayed in the inspector pane when no node is selected
- `actions`: an array of buttons to add to the header of the inspector
  - `icon`: material icon identifier
  - `tooltip`: button tooltip
  - `action`: function to be executed
- `nodeActions`: an array of buttons to add to the selected node pane
  - `icon`: material icon identifier
  - `tooltip`: button tooltip
  - `action`: function to be executed

Example:

```js
const INSPECTOR_ID = 'test-inspector'

api.addInspector({
  id: INSPECTOR_ID,
  label: 'Test inspector',
  icon: 'tab_unselected',
  treeFilterPlaceholder: 'Search for test...',
  actions: [
    {
      icon: 'star',
      tooltip: 'Test custom action',
      action: () => console.log('Meow! 🐱')
    }
  ],
  nodeActions: [
    {
      icon: 'star',
      tooltip: 'Test node custom action',
      action: nodeId => console.log('Node action:', nodeId)
    }
  ]
})
```

::: tip
It's recommended to use a variable to put the `id`, so that you can reuse it afterwards.
:::

### on.getInspectorTree

This hook is called when the devtools wants to load the tree of any custom inspector.

You have to put a condition in the callback to target only your inspector:

```js
api.on.getInspectorTree((payload) => {
  if (payload.inspectorId === 'test-inspector') {
    // Your logic here
  }
})
```

The `payload` argument:
- `app`: app instance currently active in the devtools
- `inspectorId`: id of the current custom inspector
- `filter`: string of the user input in the search field
- `rootNodes`: array of root nodes of the tree you want to display in the devtools

Each node can have those properties:
- `id`: a unique node id
- `label`: the text displayed in the tree
- `children` (optional): an array of child nodes
- `tags` (optional): an array of tag objects:
  - `label`: text displayed in the tag
  - `textColor`: text color, for example: `0x000000` for black
  - `backgroundColor`: background color, for example: `0xffffff` for white
  - `tooltip` (optional): HTML for a tooltip over the tag

Example:

```js
api.on.getInspectorTree((payload) => {
  if (payload.inspectorId === 'test-inspector') {
    payload.rootNodes = [
      {
        id: 'root',
        label: `Root (${time})`,
        children: [
          {
            id: 'child',
            label: `Child ${payload.filter}`,
            tags: [
              {
                label: 'active',
                textColor: 0x000000,
                backgroundColor: 0xFF984F
              },
              {
                label: 'test',
                textColor: 0xFFFFFF,
                backgroundColor: 0x000000
              }
            ]
          }
        ]
      }
    ]
  }
})
```

### on.getInspectorState

This hook is called when the devtools needs to load the state for the currently selected node in a custom inspector.

You have to put a condition in the callback to target only your inspector:

```js
api.on.getInspectorState((payload) => {
  if (payload.inspectorId === 'test-inspector') {
    // Your logic here
  }
})
```

The `payload` argument:
- `app`: app instance currently active in the devtools
- `inspectorId`: id of the current custom inspector
- `nodeId`: id of the currently selected node
- `state`: state sent to the devtools

The state is an object, which keys are the section names in the state inspector, and the value is an array of fields:

```js
payload.state = {
  'section 1': [
    // fields
  ],
  'section 2': [
    // fields
  ]
}
```

Each field is an object with:

- `type`: name of the section under which the field will appear
- `key`: name of the field
- `value`: value of the field
- `editable` (optional): boolean to enable edition

You can also use a [Custom value](#custom-value).

Example:

```js
api.on.getInspectorState((payload) => {
  if (payload.inspectorId === 'test-inspector') {
    if (payload.nodeId === 'root') {
      payload.state = {
        'root info': [
          {
            key: 'foo',
            value: myState.foo,
            editable: true
          },
          {
            key: 'time',
            value: time
          }
        ]
      }
    }
    else {
      payload.state = {
        'child info': [
          {
            key: 'answer',
            value: {
              _custom: {
                display: '42!!!',
                value: 42,
                tooltip: 'The answer'
              }
            }
          }
        ]
      }
    }
  }
})
```

### on.editInspectorState

If you mark a field as `editable: true`, you should also use this hook to apply the new value sent by the devtools.

You have to put a condition in the callback to target only your inspector:

```js
api.on.editInspectorState((payload) => {
  if (payload.inspectorId === 'test-inspector') {
    // Edit logic here
  }
})
```

The `payload` argument:
- `app`: app instance currently active in the devtools
- `inspectorId`: id of the current custom inspector
- `nodeId`: id of the currently selected node
- `type`: the current field type
- `path`: an array of string that represents the property edited by the user. For example, if the user edits the `myObj.myProp.hello` property, the `path` will be `['myObj', 'myProp', 'hello']`.
- `state`: object describing the edit with those properties:
  - `value`: new value
  - `newKey`: string that is set if the key of the value changed, usually when it's in an object
  - `remove`: if `true`, the value should be removed from the object or array
- `set`: an helper function that makes it easy to apply the edit on a state object

Example:

```js
api.on.editInspectorState((payload) => {
  if (payload.inspectorId === 'test-inspector') {
    if (payload.nodeId === 'root') {
      payload.set(myState)
    }
  }
})
```

### sendInspectorTree

If you need to update the tree to the user, call this function to ask for a refresh.

Example:

```js
setInterval(() => {
  api.sendInspectorTree('test-inspector')
}, 5000)
```

### sendInspectorState

If you need to update the currently selected node state to the user, call this function to ask for a refresh.

Example:

```js
setInterval(() => {
  api.sendInspectorState('test-inspector')
}, 5000)
```

### selectInspectorNode

Select a specific node in the inspector tree. The arguments are:

- `inspectorId`: the id of your inspector
- `nodeId`: the id of the node to be selected

Example:

```js
api.selectInspectorNode('test-inspector', 'some-node-id')
```

## Timeline

### now

Returns the current time with the maximum available precision.

```js
api.now()
```

### addTimelineLayer

Register a new timeline layer with this method. The options are:
- `id`: unique id of the layer. It's recommended to use a variable to store it.
- `label`: text displayed in the layer list
- `color`: color of the layer background and event graphics
- `skipScreenshots` (optional): don't trigger a screenshot for the layer events
- `groupsOnly` (optional): only display groups of events (they will be drawn as rectangles)
- `ignoreNoDurationGroups` (optional): skip groups with no duration (useful when `groupsOnly` is `true`)

Example:

```js
api.addTimelineLayer({
  id: 'test-layer',
  label: 'Test layer',
  color: 0x92A2BF
})
```

### addTimelineEvent

Use this function to send a new event on the timeline.
- `layerId`: id of the layer
- `event`: event object
  - `time`: time in millisecond when the event happened
  - `data`: state displayed when selecting the event
  - `title` (optional): text displayed in the event list
  - `subtitle` (optional): secondary text displayed in the event list
  - `logType` (optional): either `'default'`, `'warning'` or `'error'`
  - `meta` (optional): object where you can store metadata about the object that will not be displayed when it's selected
  - `groupId` (optional): id used to group multiple event together

Example:

```js
api.addTimelineEvent({
  layerId: 'test-layer',
  event: {
    time: api.now(),
    data: {
      info: 'window.keyup',
      key: event.key
    },
    groupId: event.key,
    title: 'Group test',
    meta: {
      foo: 'bar'
    }
  }
})
```

### on.inspectTimelineEvent

This hook is called when a timline event is selected. It's useful if you want to send additional information to the devtools in a lazy way.

You have to put a condition in the callback to target only your timeline layer:

```js
api.on.inspectTimelineEvent((payload) => {
  if (payload.layerId === 'test-layer') {
    // Your logic here
  }
})
```

Example:

```js
api.on.inspectTimelineEvent((payload) => {
  if (payload.layerId === 'test-layer') {
    // Async operation example
    return new Promise((resolve) => {
      setTimeout(() => {
        payload.data = {
          ...payload.data,
          hey: 'hello'
        }
        resolve()
      }, 1000)
    })
  }
})
```

### on.timelineCleared

This hook is called when the timeline is cleared by the user. Note that clearing the timeline affects all apps and layers simultaneously.

```js
api.on.timelineCleared(() => {
  console.log('timeline is cleared!')
})
```

## Settings

Plugin settings allow the user to customize the plugin behavior. Learn more about plugin settings [here](./plugins-guide.md#plugin-settings).

### getSettings

Get the current plugin settings.

Example:

```js
api.getSettings()
```

### on.setPluginSettings

Hook called when the user changes the plugin settings.

Payload properties:

- `key`: settings item
- `newValue`: new value for the changed settings
- `oldValue`: its old value (deep clone)
- `settings`: the whole current settings state object

```js
// Plugin settings change
api.on.setPluginSettings((payload) => {
  console.log(
    'plugin settings changed',
    payload.settings,
    // Info about the change
    payload.key,
    payload.newValue,
    payload.oldValue
  )
})
```

## Utilities

### getComponentInstances

Component instances on the Vue app.
- `app`: the target Vue app instance

Example:

```js
let componentInstances = []

api.on.getInspectorTree(async (payload) => {
  if (payload.inspectorId === 'test-inspector') { // e.g. custom inspector
    componentInstances = await api.getComponentInstances(app)
    for (const instance of instances) {
      payload.rootNodes.push({
        id: instance.uid.toString(),
        label: `Component ${instance.uid}`
      })
    }

    // something todo ...
  }
})
```

### getComponentBounds

Computes the component bounds on the page.

Example:

```js
api.on.inspectComponent(async (payload) => {
  if (payload.instanceData) {
    const bounds = await api.getComponentBounds(payload.componentInstance)
    payload.instanceData.state.push({
      type: stateType,
      key: 'bounds',
      value: bounds
        ? {
            left: bounds.left,
            top: bounds.top,
            width: bounds.width,
            height: bounds.height
          }
        : null
    })
  }
})
```

### getComponentName

Retrieves the component name.

Example:

```js
api.on.inspectComponent(async (payload) => {
  if (payload.instanceData) {
    const componentName = await api.getComponentName(payload.componentInstance)
    payload.instanceData.state.push({
      type: stateType,
      key: 'component name',
      value: componentName
    })
  }
})
```

### highlightElement

Highlight the element of the component.
- `instance`: the target component instance

Example:

```js
const componentInstances = [] // keeped component instance of the Vue app (e.g. `getComponentInstances`)

api.on.getInspectorState((payload) => {
  if (payload.inspectorId === 'test-inspector') { // e.g. custom inspector
    // find component instance from custom inspector node
    const instance = componentInstances.find(instance => instance.uid.toString() === payload.nodeId)

    if (instance) {
      api.highlightElement(instance)
    }

    // something todo ...
  }
})
```

### unhighlightElement

Unhighlight the element.
- `instance`: the target component instance

Example:

```js
const componentInstances = [] // keeped component instance of the Vue app (e.g. `getComponentInstances`)

api.on.getInspectorState((payload) => {
  if (payload.inspectorId === 'test-inspector') { // e.g. custom inspector
    // find component instance from custom inspector node
    const instance = componentInstances.find(instance => instance.uid.toString() === payload.nodeId)

    if (instance) {
      api.unhighlightElement(instance)
    }

    // something todo ...
  }
})
```