将插件从 Grafana 11.6.x 版本迁移到 12.0.x
本指南帮助您将插件从 Grafana 11.6.x 版本迁移到 12.0.x。
先决条件
开始迁移之前
- 备份您的插件代码
- 确保您的开发环境是最新的
- 熟悉 Grafana 11.4 中引入的响应式 API
废弃的 UI 扩展 API 已移除
Grafana 12 中已移除废弃的 UI 扩展 API,取而代之的是 Grafana 11.4 中引入的新响应式 API。以下 API 已被移除
usePluginExtensions()
usePluginLinkExtensions()
usePluginComponentExtensions()
getPluginExtensions()
getPluginLinkExtensions()
getPluginComponentExtensions()
AppPlugin.configureExtensionLink()
AppPlugin.configureExtensionComponent()
在 Grafana 12 中使用任何这些 API 都将导致错误。此外,TypeScript 类型 PluginExtensionLinkConfig
和 PluginExtensionComponentConfig
已被移除。
如果您的插件需要同时兼容 Grafana 12.0.x 及更旧版本,您可以实现运行时检查以有条件地使用相应的 API。有关更多信息,请参阅使用运行时检查管理向后兼容性。
AppPlugin.configureExtensionLink()
将 configureExtensionLink
方法替换为 addLink
方法。将 extensionPointId
参数更新为 targets
,该参数接受 string
或 string[]
。
- new AppPlugin().configureExtensionLink({
+ new AppPlugin().addLink({
- extensionPointId: PluginExtensionPoints.DashboardPanelMenu,
+ targets: PluginExtensionPoints.DashboardPanelMenu,
title: 'Component title 0',
description: 'Component description 0',
component: () => <div />,
});
AppPlugin.configureExtensionComponent()
将 configureExtensionComponent
方法替换为 addComponent
方法。将 extensionPointId
参数更新为 targets
,该参数接受 string
或 string[]
。
- new AppPlugin().configureExtensionComponent({
+ new AppPlugin().addComponent({
- extensionPointId: PluginExtensionPoints.CommandPalette,
+ targets: PluginExtensionPoints.CommandPalette,
title: 'Component title 0',
description: 'Component description 0',
component: () => <div />,
});
getPluginLinkExtensions() 和 usePluginLinkExtensions()
getPluginLinkExtensions()
函数和 usePluginLinkExtensions()
React Hook 都可以替换为 usePluginLinks()
React Hook。
- const { extensions } = getPluginLinkExtensions({
+ const { links, isLoading } = usePluginLinks({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
- const { extensions, isLoading } = usePluginLinkExtensions({
+ const { links, isLoading } = usePluginLinks({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
getPluginComponentExtensions() 和 usePluginComponentExtensions()
您可以将 getPluginComponentExtensions()
函数和 usePluginComponentExtensions()
React Hook 都替换为 usePluginComponents()
React Hook。
- const { extensions } = getPluginComponentExtensions({
+ const { components, isLoading } = usePluginComponents({
extensionPointId: 'grafana/user/profile/tab/v1',
limitPerPlugin: 2,
});
- const { extensions, isLoading } = usePluginComponentExtensions({
+ const { components, isLoading } = usePluginComponents({
extensionPointId: 'grafana/user/profile/tab/v1',
limitPerPlugin: 2,
});
getPluginExtensions() 和 usePluginExtensions()
根据用途替换 getPluginExtensions()
函数和 usePluginExtensions()
React Hook
PluginExtensionLinkConfig 和 PluginExtensionComponentConfig
类型 PluginExtensionLinkConfig
和 PluginExtensionComponentConfig
已从 @grafana/data
中移除。请分别替换为 PluginExtensionAddedLinkConfig
和 PluginExtensionAddedComponentConfig
。
GetPluginExtensionsOptions
GetPluginExtensionsOptions
类型已从 @grafana/runtime
中移除,取而代之的是与相应 Hook 参数匹配的特定类型。
快速参考
下表总结了 API 的变化,并附带了说明关键差异的注释
已废弃的 API | 等效 API | 注释 |
---|---|---|
AppPlugin.configureExtensionLink() | AppPlugin.addLink() | extensionPointId 参数重命名为 targets ,接受 string 或 string[] |
AppPlugin.configureExtensionComponent() | AppPlugin.addComponent() | extensionPointId 参数重命名为 targets ,接受 string 或 string[] |
getPluginLinkExtensions() | usePluginLinks() | 返回 { links, isLoading } 而非 { extensions } |
usePluginLinkExtensions() | usePluginLinks() | 返回 { links, isLoading } 而非 { extensions } |
getPluginComponentExtensions() | usePluginComponents() | 返回 { components, isLoading } 而非 { extensions } |
usePluginComponentExtensions() | usePluginComponents() | 返回 { components, isLoading } 而非 { extensions, isLoading } |
getPluginExtensions() | usePluginLinks() 或 usePluginComponents() | 根据扩展类型(链接或组件)拆分为两个独立的 Hook |
usePluginExtensions() | usePluginLinks() 或 usePluginComponents() | 根据扩展类型(链接或组件)拆分为两个独立的 Hook |
PluginExtensionComponentConfig | PluginExtensionAddedComponentConfig | 组件配置的类型定义已更新 |
PluginExtensionLinkConfig | PluginExtensionAddedLinkConfig | 链接配置的类型定义已更新 |
GetPluginExtensionsOptions | UsePluginLinksOptions 或 UsePluginComponentsOptions 或 UsePluginFunctionsOptions | Hook 参数的类型定义已更新 |
从 Select
迁移到 Combobox
Grafana 11.5.0 引入了新的 Combobox
组件,作为 Select
组件的替代品。Combobox
组件在设计时考虑了性能,尤其适用于处理超大数据集。详细用法指南请参见组件文档。
Select
和 MultiSelect
组件在 Grafana 12 中已被废弃,将不再获得重大更新或修复。建议迁移到 Combobox
和 MultiCombobox
。
基本用法
对于简单用例,Combobox
组件的 API 与 Select
类似。
/**
* Previous Select implementation
*/
import { SelectableValue } from '@grafana/data';
import { Select } from '@grafana/ui';
const options: SelectableValue[] = [
{ label: 'Loki', value: 'datasource-loki' },
{ label: 'Prometheus', value: 'datasource-prom' },
];
const [value, setValue] = useState<SelectableValue>();
<Select value={value} options={options} onChange={(newOption) => setValue(newOption)} />;
/**
* New Combobox implementation
*/
import { Combobox, ComboboxOption } from '@grafana/ui';
const options: ComboboxOption[] = [
{ label: 'Loki', value: 'datasource-loki' },
{ label: 'Prometheus', value: 'datasource-prom' },
];
// It is preferred to pass in only the 'value' property from options to the value prop
const [value, setValue] = useState<string>();
<Combobox value={value} options={options} onChange={(newOption) => setValue(newOption.value)} />;
异步数据加载
Combobox
组件通过传递给 options
prop 的函数处理异步数据加载。此函数会
- 接收当前输入值作为参数
- 返回解析为
ComboboxOption[]
的 Promise - 自动防抖调用,以防止过多的 API 请求
import { Combobox, ComboboxOption } from '@grafana/ui';
const [value, setValue] = useState<string>();
const loadOptions = useCallback(async (input: string): Promise<ComboboxOption[]> => {
const response = await fetch(`/api/options?query=${input}`);
return response.json();
}, []);
<Combobox value={value} options={loadOptions} onChange={(newOption) => setValue(newOption.value)} />;
首次打开时不要请求所有选项。建议仅在调用能够在服务器端过滤结果的 API 时使用此异步行为。
快速参考
下表总结了组件废弃的变化,并附带了说明关键差异的注释
已废弃 | 等效项 | 注释 |
---|---|---|
Select | Combobox | 参见下方属性表 |
MultiSelect | MultiCombobox | 参见下方属性表 |
AsyncSelect | Combobox | 对 options prop 使用异步函数 |
VirtualizedSelect | Combobox | Combobox 默认支持虚拟化 |
AsyncVirtualizedSelect | Combobox | Combobox 默认支持虚拟化 |
AsyncMultiSelect | MultiSelect | 对 options prop 使用异步函数 |
下表总结了属性的变化,并附带了说明关键差异的注释
已废弃 | 等效项 | 注释 |
---|---|---|
SelectableValue | ComboboxOption | 改为从 @grafana/ui 导出 |
SelectableValue["value"] | ComboboxOption["value"] | Value 是必需的,并且必须是原始类型 string | number |
SelectableValue["description"] | ComboboxOption["description"] | Description 不再换行,可能会被截断 |
onChange | onChange | 建议只在 state 中存储 value |
value | value | 建议只传入原始类型 string | number 的值 |
options | options | 可以是 ComboboxOption[] 或返回 Promise<ComboboxOption[]> 的函数 |
isLoading | loading | 如果使用异步 options 则不是必需的 |
allowCustomValue | createCustomValue | onChange 会发出一个类似 { label: "Foo", value: "Foo" } 的对象 |
width="auto" | width="auto" | 使用自动调整大小的输入框时,需要 minWidth |
旧 Select 组件中许多控制微小行为或自定义渲染的属性(例如 createOptionPosition
或 openMenuOnFocus
)不再受支持,以简化 API 并提供更一致的体验。如果您有需要此功能的特定用例,请在 Grafana 仓库中提交一个 issue。