加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

web页面录屏实现

发布时间:2020-05-11 07:02:25 所属栏目:编程 来源:站长网
导读:副问题#e# 在看到评述后,溘然意识到本身没有提前声名,本文可以说是一篇调研进修文,是我本身感受可行的一套方案,后续会去读读已经开源的一些相同的代码库,补足本身漏掉的一些细节,以是各人可以看成进修文,出产情形慎用。 录屏重现错误场景 假如你的应

const options = { childList: true, // 是否调查子节点的变换 subtree: true, // 是否调查全部儿女节点的变换 attributes: true, // 是否调查属性的变换 attributeOldValue: true, // 是否调查属性的变换的旧值 characterData: true, // 是否节点内容或节点文本的变换 characterDataOldValue: true, // 是否节点内容或节点文本的变换的旧值 // attributeFilter: ['class', 'src'] 不在此数组中的属性变革时将被忽略 }; const observer = new MutationObserver((mutationList) => { // mutationList: array of mutation }); observer.observe(document.documentElement, options);

行使起来很简朴,你只必要指定一个根节点和必要监控的一些选项,那么当DOM变革时,在callback函数中就会有一个mutationList,这是一个DOM的变革列表,个中mutation的布局或许为:

{ type: 'childList', // or characterData、attributes target: <DOM>, // other params }

我们行使一个数组来存放mutation,详细的callback为:

const onMutationChange = (mutationsList) => { const getFlowId = (node) => { if (node) { // 新插入的DOM没有标志,以是这里必要兼容 if (!node.__flow) node.__flow = { id: uuid() }; return node.__flow.id; } }; mutationsList.forEach((mutation) => { const { target, type, attributeName } = mutation; const record = { type, target: getFlowId(target), }; switch (type) { case 'characterData': record.value = target.nodeValue; break; case 'attributes': record.attributeName = attributeName; record.attributeValue = target.getAttribute(attributeName); break; case 'childList': record.removedNodes = [...mutation.removedNodes].map(n => getFlowId(n)); record.addedNodes = [...mutation.addedNodes].map((n) => { const snapshot = this.takeSnapshot(n); return { ...snapshot, nextSibling: getFlowId(n.nextSibling), previousSibling: getFlowId(n.previousSibling) }; }); break; } this.records.push(record); }); } function takeSnapshot(node, options = {}) { this.markNodes(node); const snapshot = { vdom: createVirtualDom(node), }; if (options.doctype === true) { snapshot.doctype = document.doctype.name; snapshot.clientWidth = document.body.clientWidth; snapshot.clientHeight = document.body.clientHeight; } return snapshot; }

这内里只必要留意,当你处理赏罚新增DOM的时辰,你必要一次增量的快照,这里如故行使Virtual DOM来记录,在后头播放的时辰,如故天生DOM,插入到父元素即可,以是这里必要参照DOM,也就是兄弟节点。

表单位素监控

上面的MutationObserver并不能监控到input等元素的值变革,以是我们必要对表单位素的值举办非凡处理赏罚。

oninput变乱监听

MDN文档: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput

变乱工具:select、input,textarea

window.addEventListener('input', this.onFormInput, true); onFormInput = (event) => { const target = event.target; if ( target && target.__flow && ['select', 'textarea', 'input'].includes(target.tagName.toLowerCase()) ) { this.records.push({ type: 'input', target: target.__flow.id, value: target.value, }); } }

在window上行使捕捉来捕捉变乱,后头也是这样处理赏罚的,这样做的缘故起因是我们是也许并常常在冒泡阶段阻止冒泡来实现一些成果,以是行使捕捉可以镌汰变乱丢失,其它,像scroll变乱是不会冒泡的,必需行使捕捉。

onchange变乱监听

MDN文档: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/oninput

input变乱没法满意type为checkbox和radio的监控,以是必要借助onchange变乱来监控

window.addEventListener('change', this.onFormChange, true); onFormChange = (event) => { const target = event.target; if (target && target.__flow) { if ( target.tagName.toLowerCase() === 'input' && ['checkbox', 'radio'].includes(target.getAttribute('type')) ) { this.records.push({ type: 'checked', target: target.__flow.id, checked: target.checked, }); } } }

onfocus变乱监听

MDN文档: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onfocus

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读