跳至主要内容

行为

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

定义行为

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

  • 作为在父元素激活时被调用的纯函数。
  • 作为在父元素激活时被激活的场景对象。

可以使用 $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`);
};
};
}

内置行为

场景库附带以下内置行为

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(),
}),
],
}),
});

源代码

查看示例源代码