move all events to an enum and update guide

This commit is contained in:
Yanzhen Yu
2026-04-01 12:00:00 +08:00
parent 3c51f79229
commit e2bc867b2e
4 changed files with 55 additions and 9 deletions

View File

@@ -249,6 +249,25 @@ new rrwebPlayer({
}); });
``` ```
#### Events
Developers may want to extend the rrweb's replayer or respond to its events. Such as giving a notification when the replayer starts to skip inactive time.
So rrweb expose a public API `on` which allow developers listen to the events and customize the reactions, and it has the following events:
| event | description |
| ---------------------- | ---------------------------------- |
| start | started to replay |
| pause | paused the replay |
| resume | resumed the replay |
| finish | finished the replay |
| fullsnapshot-rebuilded | rebuilded a full snapshot |
| load-stylesheet-start | started to load remote stylesheets |
| load-stylesheet-end | loaded remote stylesheets |
| skip-start | started to skip inactive time |
| skip-end | skipped inactive time |
The rrweb-replayer also re-expose the event listener via a `component.addEventListener` API.
## API ## API
### rrweb ### rrweb

View File

@@ -17,6 +17,7 @@ import {
actionWithDelay, actionWithDelay,
incrementalSnapshotEvent, incrementalSnapshotEvent,
incrementalData, incrementalData,
ReplayerEvents,
} from '../types'; } from '../types';
import { mirror } from '../utils'; import { mirror } from '../utils';
import injectStyleRules from './styles/inject-style'; import injectStyleRules from './styles/inject-style';
@@ -125,11 +126,12 @@ export class Replayer {
} }
this.timer.addActions(actions); this.timer.addActions(actions);
this.timer.start(); this.timer.start();
this.emitter.emit(ReplayerEvents.Start);
} }
public pause() { public pause() {
this.timer.clear(); this.timer.clear();
this.emitter.emit('pause'); this.emitter.emit(ReplayerEvents.Pause);
} }
public resume(timeOffset = 0) { public resume(timeOffset = 0) {
@@ -151,7 +153,7 @@ export class Replayer {
} }
this.timer.addActions(actions); this.timer.addActions(actions);
this.timer.start(); this.timer.start();
this.emitter.emit('resume'); this.emitter.emit(ReplayerEvents.Resume);
} }
private setupDom() { private setupDom() {
@@ -200,7 +202,7 @@ export class Replayer {
break; break;
case EventType.Meta: case EventType.Meta:
castFn = () => castFn = () =>
this.emitter.emit('resize', { this.emitter.emit(ReplayerEvents.Resize, {
width: event.data.width, width: event.data.width,
height: event.data.height, height: event.data.height,
}); });
@@ -241,7 +243,7 @@ export class Replayer {
speed: Math.min(Math.round(skipTime / SKIP_TIME_INTERVAL), 360), speed: Math.min(Math.round(skipTime / SKIP_TIME_INTERVAL), 360),
}; };
this.setConfig(payload); this.setConfig(payload);
this.emitter.emit('skip-start', payload); this.emitter.emit(ReplayerEvents.SkipStart, payload);
} }
} }
}; };
@@ -255,7 +257,7 @@ export class Replayer {
this.lastPlayedEvent = event; this.lastPlayedEvent = event;
if (event === this.events[this.events.length - 1]) { if (event === this.events[this.events.length - 1]) {
this.restoreSpeed(); this.restoreSpeed();
this.emitter.emit('finish'); this.emitter.emit(ReplayerEvents.Finish);
} }
}; };
return wrappedCastFn; return wrappedCastFn;
@@ -278,6 +280,7 @@ export class Replayer {
for (let idx = 0; idx < injectStyleRules.length; idx++) { for (let idx = 0; idx < injectStyleRules.length; idx++) {
(styleEl.sheet! as CSSStyleSheet).insertRule(injectStyleRules[idx], idx); (styleEl.sheet! as CSSStyleSheet).insertRule(injectStyleRules[idx], idx);
} }
this.emitter.emit(ReplayerEvents.FullsnapshotRebuilded);
this.waitForStylesheetLoad(); this.waitForStylesheetLoad();
} }
@@ -295,7 +298,7 @@ export class Replayer {
if (!css.sheet) { if (!css.sheet) {
if (unloadSheets.size === 0) { if (unloadSheets.size === 0) {
this.pause(); this.pause();
this.emitter.emit('wait-stylesheet'); this.emitter.emit(ReplayerEvents.LoadStylesheetStart);
timer = window.setTimeout(() => { timer = window.setTimeout(() => {
this.resume(); this.resume();
// mark timer was called // mark timer was called
@@ -307,7 +310,7 @@ export class Replayer {
unloadSheets.delete(css); unloadSheets.delete(css);
if (unloadSheets.size === 0 && timer !== -1) { if (unloadSheets.size === 0 && timer !== -1) {
this.resume(); this.resume();
this.emitter.emit('stylesheet-loaded'); this.emitter.emit(ReplayerEvents.LoadStylesheetEnd);
if (timer) { if (timer) {
window.clearTimeout(timer); window.clearTimeout(timer);
} }
@@ -514,7 +517,7 @@ export class Replayer {
break; break;
} }
case IncrementalSource.ViewportResize: case IncrementalSource.ViewportResize:
this.emitter.emit('resize', { this.emitter.emit(ReplayerEvents.Resize, {
width: d.width, width: d.width,
height: d.height, height: d.height,
}); });
@@ -603,7 +606,7 @@ export class Replayer {
} }
const payload = { speed: this.noramlSpeed }; const payload = { speed: this.noramlSpeed };
this.setConfig(payload); this.setConfig(payload);
this.emitter.emit('skip-end', payload); this.emitter.emit(ReplayerEvents.SkipEnd, payload);
this.noramlSpeed = -1; this.noramlSpeed = -1;
} }

View File

@@ -249,3 +249,16 @@ export type actionWithDelay = {
doAction: () => void; doAction: () => void;
delay: number; delay: number;
}; };
export enum ReplayerEvents {
Start = 'start',
Pause = 'pause',
Resume = 'resume',
Resize = 'resize',
Finish = 'finish',
FullsnapshotRebuilded = 'fullsnapshot-rebuilded',
LoadStylesheetStart = 'load-stylesheet-start',
LoadStylesheetEnd = 'load-stylesheet-end',
SkipStart = 'skip-start',
SkipEnd = 'skip-end',
}

11
typings/types.d.ts vendored
View File

@@ -198,4 +198,15 @@ export declare type actionWithDelay = {
doAction: () => void; doAction: () => void;
delay: number; delay: number;
}; };
export declare enum ReplayerEvents {
Pause = "pause",
Resume = "resume",
Resize = "resize",
Finish = "finish",
FullsnapshotRebuilded = "fullsnapshot-rebuilded",
LoadStylesheetStart = "load-stylesheet-start",
LoadStylesheetEnd = "load-stylesheet-end",
SkipStart = "skip-start",
SkipEnd = "skip-end"
}
export {}; export {};