插件 API 参考

警告

该 API 仅在 Vue Devtools 6+ 中可用

插件设置

setupDevtoolsPlugin

注册一个 devtools 插件。描述插件并提供对 devtools API 的访问。

setupDevtoolsPlugin (pluginDescriptor, setupFn)

插件描述符是一个对象,用于向 Vue devtools 用户描述 devtools 插件。

它具有以下属性

  • id: 所有可能插件之间唯一的 id。建议使用反向域名表示法,例如:org.vuejs.router,或 npm 包名。
  • app: 当前应用程序实例。devtools 针对特定应用程序,因此您必须指定 devtools 插件将在哪个应用程序实例上运行。
  • label: 显示给用户的标签。建议使用插件的用户友好名称,例如:'Vue Router'。不要在名称中添加 'devtools''plugin',因为用户在使用您的 Vue 插件时已经可以看到这个 devtools 插件。
  • packageName (可选): 与 devtools 插件关联的 npm 包名,例如 'vue-router'
  • homepage (可选): 文档的 URL。
  • logo (可选): Vue 插件的 logo 的 URL。
  • componentStateTypes (可选): 您将添加到组件检查器的自定义组件状态部分名称的数组。如果您向组件检查器添加新状态,则应在此处声明其部分,以便 devtools 可以显示插件图标。
  • disableAppScope (可选): 如果设置为 true,则使用此插件注册的钩子将不会作用域到关联的应用程序。在这种情况下,您可能需要使用 app 负载属性来检查每个钩子中的当前应用程序是什么。
  • disablePluginScope (可选): 如果设置为 true,则使用此插件注册的钩子将不会作用域到当前插件。在这种情况下,您可能需要使用 pluginId 负载属性(取决于钩子)来检查每个钩子中的相关插件是什么。
  • enableEarlyProxy (可选): 如果设置为 true,即使 Vue devtools 尚未使用插件 API 的代理和缓冲区队列连接,插件也会运行。如果您需要在用户打开 devtools 之前添加时间线事件,这将很有用。
  • settings (可选): 描述插件设置的对象。了解有关插件设置的更多信息 这里.

示例

const stateType = 'routing properties'

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

组件检查器

on.visitComponentTree

使用此钩子在组件树中添加标签。

payload 参数

  • app: 当前在 devtools 中处于活动状态的应用程序实例
  • componentInstance: 树中当前组件实例数据
  • treeNode: 将发送到 devtools 的树节点
  • filter: 组件检查器中树上方搜索输入的当前值

示例

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

使用此钩子向所选组件的状态添加新信息。

payload 参数

  • app: 当前在 devtools 中处于活动状态的应用程序实例
  • componentInstance: 树中当前组件实例数据
  • instanceData: 将发送到 devtools 的状态

要添加新状态,您可以将新字段推送到 instanceData.state 数组中

基本字段

  • type: 字段将出现在其下的部分的名称
  • key: 字段的名称
  • value: 字段的值
  • editable (可选): 布尔值以启用编辑

自定义值

默认情况下,devtools 将根据字段是对象、数组等来显示您的字段。您可以通过将 { _custom: {} } 对象放入值来自定义字段显示。

_custom 对象具有以下属性

  • type: 显示值的类型。示例:'router''component''service'...
  • display: 代替值显示的文本。示例:'5 minutes'
  • tooltip: 悬停在值文本 (display) 上时的工具提示
  • value: 实际值
  • abstract: 不显示任何值。对索引很有用。例如,Set 对象具有抽象索引子字段:01...
  • readOnly: 将此值标记为不可编辑
  • fields: 配置直接子字段的对象
    • 抽象
  • actions: 要添加到字段的按钮数组
    • icon: 材料图标标识符
    • tooltip: 按钮工具提示
    • action: 要执行的函数

当您使用 type 属性添加新部分时,您应该在调用 setupDevtoolsPlugin 时在插件描述符的 componentStateTypes 数组中声明它们。

示例

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

如果您将字段标记为 editable: true,则还应使用此钩子来应用 devtools 发送的新值。

您必须在回调中添加一个条件,以仅针对您的字段类型。

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

payload 参数

  • app: 当前在 devtools 中处于活动状态的应用程序实例
  • type: 当前字段类型
  • path: 表示用户编辑的属性的字符串数组。例如,如果用户编辑 myObj.myProp.hello 属性,则 path 将为 ['myObj', 'myProp', 'hello']
  • state: 使用以下属性描述编辑的对象
    • value: 新值
    • newKey: 如果值的键已更改,则设置的字符串,通常是在对象中
    • remove: 如果为 true,则应从对象或数组中删除该值
  • set: 一个辅助函数,可以轻松地将编辑应用于状态对象

示例

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

这是一个可编辑的自定义组件字段的完整示例

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)
  }
})

如您所见,您应该使用一个对象来保存字段值,以便可以将其分配给它。

notifyComponentUpdate

如果您的状态已更改,您可以告诉 devtools 使用 notifyComponentUpdate 方法刷新所选组件状态

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

您还可以传递一个特定的组件实例

api.notifyComponentUpdate(vm)

自定义检查器

自定义检查器可用于使用可检查树显示有关库的调试信息。

addInspector

此函数注册一个新的自定义检查器。

选项是

  • id: 唯一的自定义检查器 id
  • label: 在 Inspector 子菜单中显示的标签
  • icon (可选): 材料图标代码,例如 'star'
  • treeFilterPlaceholder (可选): 树上方过滤器输入的占位符
  • stateFilterPlaceholder (可选): 状态检查器中过滤器输入的占位符
  • noSelectionText (可选): 未选择任何节点时在检查器窗格中显示的文本
  • actions: 要添加到检查器标题的按钮数组
    • icon: 材料图标标识符
    • tooltip: 按钮工具提示
    • action: 要执行的函数
  • nodeActions: 要添加到所选节点窗格的按钮数组
    • icon: 材料图标标识符
    • tooltip: 按钮工具提示
    • action: 要执行的函数

示例

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)
    }
  ]
})

提示

建议使用一个变量来放置 id,以便您可以在之后重复使用它。

on.getInspectorTree

当开发者工具想要加载任何自定义检查器的树时,会调用此钩子。

您需要在回调中添加一个条件,以仅针对您的检查器。

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

payload 参数

  • app: 当前在 devtools 中处于活动状态的应用程序实例
  • inspectorId: 当前自定义检查器的 ID
  • filter: 搜索字段中用户输入的字符串
  • rootNodes: 您想要在开发者工具中显示的树的根节点数组

每个节点可以具有以下属性

  • id: 唯一的节点 ID
  • label: 在树中显示的文本
  • children (可选): 子节点数组
  • tags (可选): 标签对象数组
    • label: 在标签中显示的文本
    • textColor: 文本颜色,例如:0x000000 表示黑色
    • backgroundColor: 背景颜色,例如:0xffffff 表示白色
    • tooltip (可选): 标签上的工具提示的 HTML

示例

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

当开发者工具需要加载自定义检查器中当前选中节点的状态时,会调用此钩子。

您需要在回调中添加一个条件,以仅针对您的检查器。

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

payload 参数

  • app: 当前在 devtools 中处于活动状态的应用程序实例
  • inspectorId: 当前自定义检查器的 ID
  • nodeId: 当前选中节点的 ID
  • state: 发送到开发者工具的状态

状态是一个对象,其键是状态检查器中的部分名称,值是字段数组

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

每个字段都是一个对象,具有

  • type: 字段将出现在其下的部分的名称
  • key: 字段的名称
  • value: 字段的值
  • editable (可选): 布尔值以启用编辑

您也可以使用 自定义值

示例

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

如果您将字段标记为 editable: true,则还应使用此钩子来应用 devtools 发送的新值。

您需要在回调中添加一个条件,以仅针对您的检查器。

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

payload 参数

  • app: 当前在 devtools 中处于活动状态的应用程序实例
  • inspectorId: 当前自定义检查器的 ID
  • nodeId: 当前选中节点的 ID
  • type: 当前字段类型
  • path: 表示用户编辑的属性的字符串数组。例如,如果用户编辑 myObj.myProp.hello 属性,则 path 将为 ['myObj', 'myProp', 'hello']
  • state: 使用以下属性描述编辑的对象
    • value: 新值
    • newKey: 如果值的键已更改,则设置的字符串,通常是在对象中
    • remove: 如果为 true,则应从对象或数组中删除该值
  • set: 一个辅助函数,可以轻松地将编辑应用于状态对象

示例

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

sendInspectorTree

如果您需要将树更新给用户,请调用此函数以请求刷新。

示例

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

sendInspectorState

如果您需要将当前选中节点的状态更新给用户,请调用此函数以请求刷新。

示例

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

selectInspectorNode

在检查器树中选择一个特定节点。参数是

  • inspectorId: 您检查器的 ID
  • nodeId: 要选择的节点的 ID

示例

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

Timeline

now

返回当前时间,具有最大可用精度。

api.now()

addTimelineLayer

使用此方法注册一个新的时间线层。选项是

  • id: 层的唯一 ID。建议使用变量来存储它。
  • label: 在层列表中显示的文本
  • color: 层背景和事件图形的颜色
  • skipScreenshots (可选): 不要为层事件触发屏幕截图
  • groupsOnly (可选): 仅显示事件组(它们将被绘制为矩形)
  • ignoreNoDurationGroups (可选): 跳过没有持续时间的组(当 groupsOnlytrue 时有用)

示例

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

addTimelineEvent

使用此函数在时间线上发送一个新事件。

  • layerId: 层的 ID
  • event: 事件对象
    • time: 事件发生时的毫秒时间
    • data: 选择事件时显示的状态
    • title (可选): 在事件列表中显示的文本
    • subtitle (可选): 在事件列表中显示的辅助文本
    • logType (可选): 'default''warning''error' 之一
    • meta (可选): 对象,您可以在其中存储有关对象的元数据,这些元数据在选择对象时不会显示
    • groupId (可选): 用于将多个事件分组在一起的 ID

示例

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

当选择时间线事件时,会调用此钩子。如果您想以延迟的方式将其他信息发送到开发者工具,这很有用。

您需要在回调中添加一个条件,以仅针对您的时间线层。

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

示例

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

当用户清除时间线时,会调用此钩子。请注意,清除时间线会同时影响所有应用程序和层。

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

Settings

插件设置允许用户自定义插件行为。了解有关插件设置的更多信息 这里

getSettings

获取当前插件设置。

示例

api.getSettings()

on.setPluginSettings

当用户更改插件设置时调用的钩子。

有效负载属性

  • key: 设置项
  • newValue: 更改设置的新值
  • oldValue: 它的旧值(深层克隆)
  • settings: 整个当前设置状态对象
// 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

Vue 应用程序上的组件实例。

  • app: 目标 Vue 应用程序实例

示例

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

计算页面上的组件边界。

示例

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

检索组件名称。

示例

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

突出显示组件的元素。

  • instance: 目标组件实例

示例

let 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

取消突出显示元素。

  • instance: 目标组件实例

示例

let 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 ...
  }
})