跳到主要内容

行为

通过行为,您可以实现自定义场景逻辑,这些逻辑将作为副作用执行。行为对于执行副作用非常有用,例如有条件地隐藏场景中的元素或在场景对象之间附加共享功能。

定义行为

行为可以通过两种方式实现

  • 作为纯函数,在其父级被激活时调用。
  • 作为场景对象,在其父级被激活时激活。

行为可以使用 $behaviors 状态属性附加到场景对象。例如,您可以将行为附加到 SceneQueryRunner

const queryRunner = new SceneQueryRunner({
$behaviors: [
/* list of behaviors */
],

datasource: {
type: 'prometheus',
uid: 'gdev-prometheus',
},
queries: [
{
refId: 'A',
range: true,
format: 'time_series',
expr: 'rate(prometheus_http_requests_total[5m])',
},
],
});

作为纯函数的行为

行为可以实现为无状态函数,当行为的父级被激活时调用。此函数可以返回一个停用处理程序,以便在父级停用时调用。

下面您将找到一个简单的无状态行为,当行为的父级激活/停用或其状态更改时,它将在开发者控制台中记录。

const StatelessLoggerBehavior = (parent: SceneObject) => {
console.log(`${parent.state.key} activated`);

parent.subscribeToState(() => {
console.log(`${parent.state.key} state changed`);
});

return () => {
console.log(`${parent.state.key} deactivated`);
};
};

作为场景对象的行为

将行为实现为场景对象与实现自定义场景对象完全相同。下面的示例说明了前一个示例中的扩展日志记录器行为,该行为将在场景对象激活/停用时以及基于提供的配置批量处理父状态更新日志时,在开发者控制台中记录。

interface StatefulLoggerBehaviorState extends SceneObjectState {
// Size of the batch of state updates
batchStateUpdates: number;
}

class StatefulLoggerBehavior extends SceneObjectBase<StatefulLoggerBehaviorState> {
private _batchedStateUpdates: Array<SceneObjectState> = [];

constructor(state: Partial<StatefulLoggerBehaviorState>) {
super({
batchStateUpdates: 5,
...state,
});
this.addActivationHandler(this._onActivate);
}

private _onActivate = () => {
const parent = this.parent;

if (!parent) {
throw new Error('LoggerBehavior must be attached to a parent object');
}

console.log(`StatefulLoggerBehavior: ${parent.state.key} activated`);

parent.subscribeToState(() => {
this._batchedStateUpdates.push(parent.state);

if (this._batchedStateUpdates.length === this.state.batchStateUpdates) {
console.log(`StatefulLoggerBehavior: ${parent.state.key} state changed batch`, this._batchedStateUpdates);
this._batchedStateUpdates = [];
}
});

return () => {
console.log(`StatefulLoggerBehavior: ${parent.state.key} deactivated`);
};
};
}

内置行为

Scenes 库附带以下内置行为

ActWhenVariableChanged

当变量更改时执行副作用。

用法

假设场景中有一个名为 myVariable 的变量,您可以配置在变量值更改时执行的副作用

import { behaviors } from '@grafana/scenes';

const logWhenVariableChanges = new behaviors.ActWhenVariableChanged({
variableName: 'myVariable',
onChange: (variable) => {
console.log(`myVariable value changed: ${variable.state.value}`);
},
});

CursorSync

创建一个共享光标作用域,用于配置跨多个面板的光标同步。

用法

在下面的示例中,CursorSync 行为用于同步场景中所有面板的光标

import {
behaviors,
EmbeddedScene,
PanelBuilders,
SceneFlexItem,
SceneFlexLayout,
SceneQueryRunner,
SceneTimeRange,
} from '@grafana/scenes';

const httpRequests = new SceneQueryRunner({
datasource: {
type: 'prometheus',
uid: 'gdev-prometheus',
},
queries: [
{
refId: 'A',
range: true,
format: 'time_series',
expr: 'rate(prometheus_http_requests_total[5m])',
},
],
});

const cpuUsage = new SceneQueryRunner({
datasource: {
type: 'prometheus',
uid: 'gdev-prometheus',
},
queries: [
{
refId: 'A',
expr: 'avg by (job, instance, mode) (rate(node_cpu_seconds_total[5m]))',
},
],
});

const scene = new EmbeddedScene({
$timeRange: new SceneTimeRange({ from: 'now-5m', to: 'now' }),
$behaviors: [new behaviors.CursorSync({ key: 'cursor-sync-scope', sync: DashboardCursorSync.Tooltip })],
body: new SceneFlexLayout({
direction: 'row',
children: [
new SceneFlexItem({
width: '50%',
height: 300,
body: PanelBuilders.timeseries().setData(httpRequests).setTitle('HTTP Requests').build(),
}),
new SceneFlexItem({
width: '50%',
height: 300,
body: PanelBuilders.timeseries()
.setTitle('CPU Usage')
.setTimeRange(new SceneTimeRange({ from: 'now-6h', to: 'now' }))
.setData(cpuUsage)
.build(),
}),
],
}),
});

源代码

查看示例源代码