如何向contenteditable="true"的富文本编辑器快速传入大量文本
解决方案
核心思路是放弃逐字符模拟键盘输入的逻辑,直接通过Puppeteer向页面注入JS执行内容插入,全程不会触碰系统剪贴板,3万字符插入耗时可控制在100ms以内,且能正常触发Slate等富文本编辑器的状态更新。
代码修改示例
你只需要替换原有代码中全选、清空、输入文本的三段逻辑即可:
export const edit = async () => { const browser = await launch({ headless: false }); const page = await browser.newPage(); try { await page.setUserAgent( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0' ); await page.goto('https://www.slatejs.org/examples/richtext'); const editableSelector = '[contenteditable="true"]'; await page.waitForSelector(editableSelector); // 核心逻辑:在页面上下文执行批量插入,不会触碰系统剪贴板 await page.evaluate((selector, content) => { const editable = document.querySelector(selector); editable.focus(); // 全选+清空原有内容 document.execCommand('selectAll', false, null); document.execCommand('delete', false, null); // 批量插入目标文本 document.execCommand('insertText', false, content); }, editableSelector, aLargeAmountOfText); } finally { await page.screenshot({ path: 'example.png' }); await browser.close(); } };
兼容备选方案
如果部分场景下execCommand出现兼容问题,可以替换为基于InputEvent的实现,同样不会触碰系统剪贴板:
await page.evaluate((selector, content) => { const editable = document.querySelector(selector); editable.focus(); document.execCommand('selectAll', false, null); document.execCommand('delete', false, null); // 内存内创建DataTransfer对象,仅在当前页面上下文生效 const dataTransfer = new DataTransfer(); dataTransfer.setData('text/plain', content); editable.dispatchEvent(new InputEvent('beforeinput', { inputType: 'insertFromPaste', data: null, dataTransfer, bubbles: true, cancelable: true })); }, editableSelector, aLargeAmountOfText);
方案优势
- 执行效率极高,无逐字符输入的性能损耗
- 全程在浏览器内存上下文运行,不会和系统剪贴板、输入设备交互,不影响其他操作
- 会主动触发富文本编辑器监听的
beforeinput、input事件,编辑器内部状态会同步更新,不会出现DOM内容和编辑器状态不一致的问题 - 不需要更换技术栈,基于原有的Puppeteer逻辑即可修改完成
内容的提问来源于stack exchange,提问作者Daniel Kaplan
相关产品推荐
相关产品推荐

