行为
通过行为,您可以实现自定义场景逻辑,这些逻辑将作为副作用执行。行为对于执行副作用非常有用,例如有条件地隐藏场景中的元素或在场景对象之间附加共享功能。
定义行为
行为可以通过两种方式实现
- 作为纯函数,在其父级被激活时调用。
- 作为场景对象,在其父级被激活时激活。
行为可以使用 $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(),
}),
],
}),
});