resolve #13 add warning messages when target is not found

This commit is contained in:
Yanzhen Yu
2019-01-05 14:18:07 +08:00
parent 727009177b
commit 6973ce2c8d
4 changed files with 47 additions and 21 deletions

View File

@@ -134,12 +134,13 @@ replayer.play();
The replayer accepts options as its constructor's second parameter, and it has the following options: The replayer accepts options as its constructor's second parameter, and it has the following options:
| key | default | description | | key | default | description |
| ------------ | ------------- | ------------------------------------- | | ------------ | ------------- | ----------------------------------------------- |
| speed | 1 | replay speed ratio | | speed | 1 | replay speed ratio |
| root | document.body | the root element of replayer | | root | document.body | the root element of replayer |
| loadTimeout | 0 | timeout of loading remote style sheet | | loadTimeout | 0 | timeout of loading remote style sheet |
| skipInactive | false | whether to skip inactive time | | skipInactive | false | whether to skip inactive time |
| showWarning | true | whether to print warning messages during replay |
#### Use rrweb-player #### Use rrweb-player

View File

@@ -136,6 +136,7 @@ replayer.play();
| root | document.body | 回放时使用的 HTML 元素 | | root | document.body | 回放时使用的 HTML 元素 |
| loadTimeout | 0 | 加载异步样式表的超时时长 | | loadTimeout | 0 | 加载异步样式表的超时时长 |
| skipInactive | false | 是否快速跳过无用户操作的阶段 | | skipInactive | false | 是否快速跳过无用户操作的阶段 |
| showWarning | true | 是否在回放过程中打印警告信息 |
#### 使用 rrweb-player #### 使用 rrweb-player

View File

@@ -16,6 +16,7 @@ import {
missingNode, missingNode,
actionWithDelay, actionWithDelay,
incrementalSnapshotEvent, incrementalSnapshotEvent,
incrementalData,
} from '../types'; } from '../types';
import { mirror } from '../utils'; import { mirror } from '../utils';
import injectStyleRules from './styles/inject-style'; import injectStyleRules from './styles/inject-style';
@@ -30,6 +31,8 @@ smoothscroll.polyfill();
// tslint:disable-next-line // tslint:disable-next-line
const mitt = (mittProxy as any).default || mittProxy; const mitt = (mittProxy as any).default || mittProxy;
const REPLAY_CONSOLE_PREFIX = '[replayer]';
export class Replayer { export class Replayer {
public wrapper: HTMLDivElement; public wrapper: HTMLDivElement;
@@ -64,6 +67,7 @@ export class Replayer {
root: document.body, root: document.body,
loadTimeout: 0, loadTimeout: 0,
skipInactive: false, skipInactive: false,
showWarning: true,
}; };
this.config = Object.assign({}, defaultConfig, config); this.config = Object.assign({}, defaultConfig, config);
@@ -324,7 +328,7 @@ export class Replayer {
d.removes.forEach(mutation => { d.removes.forEach(mutation => {
const target = mirror.getNode(mutation.id); const target = mirror.getNode(mutation.id);
if (!target) { if (!target) {
return; return this.warnTargetNotFound(d, mutation.id);
} }
const parent = (mirror.getNode( const parent = (mirror.getNode(
mutation.parentId!, mutation.parentId!,
@@ -410,9 +414,10 @@ export class Replayer {
this.mouse.style.left = `${p.x}px`; this.mouse.style.left = `${p.x}px`;
this.mouse.style.top = `${p.y}px`; this.mouse.style.top = `${p.y}px`;
const target = mirror.getNode(p.id); const target = mirror.getNode(p.id);
if (target) { if (!target) {
this.hoverElements((target as Node) as Element); return this.warnTargetNotFound(d, p.id);
} }
this.hoverElements((target as Node) as Element);
}, },
delay: p.timeOffset + e.timestamp - this.baselineTime, delay: p.timeOffset + e.timestamp - this.baselineTime,
}; };
@@ -428,13 +433,16 @@ export class Replayer {
break; break;
} }
const event = new Event(MouseInteractions[d.type].toLowerCase()); const event = new Event(MouseInteractions[d.type].toLowerCase());
const target = (mirror.getNode(d.id) as Node) as HTMLElement; const target = mirror.getNode(d.id);
if (!target) {
return this.warnTargetNotFound(d, d.id);
}
switch (d.type) { switch (d.type) {
case MouseInteractions.Blur: case MouseInteractions.Blur:
target.blur(); ((target as Node) as HTMLElement).blur();
break; break;
case MouseInteractions.Focus: case MouseInteractions.Focus:
target.focus({ ((target as Node) as HTMLElement).focus({
preventScroll: true, preventScroll: true,
}); });
break; break;
@@ -465,8 +473,11 @@ export class Replayer {
if (d.id === -1) { if (d.id === -1) {
break; break;
} }
const target = mirror.getNode(d.id) as Node; const target = mirror.getNode(d.id);
if (target === this.iframe.contentDocument) { if (!target) {
return this.warnTargetNotFound(d, d.id);
}
if ((target as Node) === this.iframe.contentDocument) {
this.iframe.contentWindow!.scrollTo({ this.iframe.contentWindow!.scrollTo({
top: d.y, top: d.y,
left: d.x, left: d.x,
@@ -474,8 +485,8 @@ export class Replayer {
}); });
} else { } else {
try { try {
(target as Element).scrollTop = d.y; ((target as Node) as Element).scrollTop = d.y;
(target as Element).scrollLeft = d.x; ((target as Node) as Element).scrollLeft = d.x;
} catch (error) { } catch (error) {
/** /**
* Seldomly we may found scroll target was removed before * Seldomly we may found scroll target was removed before
@@ -501,12 +512,13 @@ export class Replayer {
if (d.id === -1) { if (d.id === -1) {
break; break;
} }
const target: HTMLInputElement = (mirror.getNode( const target = mirror.getNode(d.id);
d.id, if (!target) {
) as Node) as HTMLInputElement; return this.warnTargetNotFound(d, d.id);
}
try { try {
target.checked = d.isChecked; ((target as Node) as HTMLInputElement).checked = d.isChecked;
target.value = d.text; ((target as Node) as HTMLInputElement).value = d.text;
} catch (error) { } catch (error) {
// for safe // for safe
} }
@@ -577,4 +589,15 @@ export class Replayer {
this.emitter.emit('skip-end', payload); this.emitter.emit('skip-end', payload);
this.noramlSpeed = -1; this.noramlSpeed = -1;
} }
private warnTargetNotFound(d: incrementalData, id: number) {
if (!this.config.showWarning) {
return;
}
console.warn(
REPLAY_CONSOLE_PREFIX,
`target with id '${id}' not found in`,
d,
);
}
} }

View File

@@ -229,6 +229,7 @@ export type playerConfig = {
root: Element; root: Element;
loadTimeout: number; loadTimeout: number;
skipInactive: Boolean; skipInactive: Boolean;
showWarning: Boolean;
}; };
export type playerMetaData = { export type playerMetaData = {