HarmonyOS ArkWeb 系列之用户一复制,我就知道——剪贴板事件监听实战

文章目录

      • 剪贴板事件有哪几个
      • ArkTS 侧配置
      • H5 侧的事件监听实现
      • 流程图:copy 事件拦截修改
      • 三种事件的使用场景对比
      • 一个实用的"只允许粘贴纯文本"方案
      • 踩坑记录
      • 写在最后

上一篇讲了怎么用代码主动读写剪贴板。但有时候需求不是主动操作,而是监听——用户在我的 Web 页面里做了复制/粘贴/剪切操作,我想拦截、修改、或者记录一下。
这就是剪贴板事件(Clipboard Events)的用武之地。

剪贴板事件有哪几个

浏览器标准里定义了三个剪贴板相关事件:

事件名触发时机能做什么
copy用户触发复制(Ctrl+C 或右键复制)修改复制内容、阻止默认复制
cut用户触发剪切(Ctrl+X 或右键剪切)修改剪切内容、阻止默认剪切
paste用户触发粘贴(Ctrl+V 或右键粘贴)处理粘贴内容、阻止默认粘贴

这三个事件都挂在 DOM 元素上,可以给具体元素监听,也可以给document监听(捕获页面上所有的操作)。

ArkTS 侧配置

和上一篇一样,ArkTS 这边只需要加载对应的 HTML 文件,Web 组件本身不需要特殊配置:

import{webview}from'@kit.ArkWeb';@Entry@Componentstruct WebComponent{controller:webview.WebviewController=newwebview.WebviewController();build(){Column(){Web({src:$rawfile('clipboard_event.html'),controller:this.controller})}}}

H5 侧的事件监听实现

下面是一个完整的示例,演示如何监听并处理三种剪贴板事件:

<!DOCTYPEhtml><htmllang="zh"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>剪贴板事件监听演示</title><style>body{font-family:sans-serif;padding:20px;}#editArea{width:100%;height:120px;border:2px solid #ddd;padding:10px;font-size:16px;border-radius:4px;box-sizing:border-box;}#eventLog{margin-top:16px;padding:10px;background:#f5f5f5;border-radius:4px;min-height:80px;font-size:14px;color:#333;}.event-copy{color:#2196f3;}.event-cut{color:#ff9800;}.event-paste{color:#4caf50;}</style></head><body><h2>剪贴板事件监听</h2><p>在下方文本框中进行复制、剪切、粘贴操作,右侧日志区会实时显示事件信息。</p><textareaid="editArea"placeholder="在这里输入内容,然后尝试复制/剪切/粘贴...">选中这段文字,然后按 Ctrl+C 试试看。</textarea><divid="eventLog">(事件日志将显示在这里)</div><script>consteditArea=document.getElementById('editArea');consteventLog=document.getElementById('eventLog');functionappendLog(type,message){constline=document.createElement('div');line.className='event-'+type;line.textContent=`[${newDate().toLocaleTimeString()}]${message}`;eventLog.insertBefore(line,eventLog.firstChild);// 最多保留 10 条日志while(eventLog.children.length>10){eventLog.removeChild(eventLog.lastChild);}}// 监听 copy 事件editArea.addEventListener('copy',function(event){constselectedText=window.getSelection().toString();appendLog('copy',`copy 事件触发,选中内容:「${selectedText}`);// 进阶用法:修改复制内容(比如追加版权信息)if(selectedText&&event.clipboardData){constmodifiedText=selectedText+'\n\n—— 来自我的应用';event.clipboardData.setData('text/plain',modifiedText);event.preventDefault();// 阻止默认复制行为,使用我们修改后的内容appendLog('copy',`已修改复制内容,追加了版权信息`);}});// 监听 cut 事件editArea.addEventListener('cut',function(event){constselectedText=window.getSelection().toString();appendLog('cut',`cut 事件触发,剪切内容:「${selectedText}`);// 这里不阻止默认行为,让系统正常执行剪切});// 监听 paste 事件editArea.addEventListener('paste',function(event){// 获取粘贴内容(不阻止默认行为时,paste 事件的 clipboardData 是只读的)constpastedText=event.clipboardData?event.clipboardData.getData('text/plain'):'';appendLog('paste',`paste 事件触发,粘贴内容:「${pastedText}`);// 进阶用法:过滤敏感词if(pastedText.includes('敏感词')){event.preventDefault();constfiltered=pastedText.replace(/敏感词/g,'***');// 手动插入过滤后的内容document.execCommand('insertText',false,filtered);appendLog('paste',`已过滤敏感词并粘贴`);}});</script></body></html>

代码里有几个关键点值得注意:

event.clipboardData是事件对象上携带的剪贴板数据对象。在copy/cut事件里可以读写;在paste事件里通常只读。

event.preventDefault()阻止浏览器的默认行为。比如在copy事件里调用它,浏览器就不会把选中的文本复制到剪贴板,而是使用你通过setData()设置的内容。

window.getSelection().toString()获取页面上当前选中的文本。

流程图:copy 事件拦截修改

三种事件的使用场景对比

copy 事件最常见的用途

  • 追加版权声明(「复制自 XXX,原文链接:…」)
  • 格式化复制内容(去掉多余空格、换行等)
  • 统计用户复制了什么内容(数据分析)

cut 事件常见用途

  • 记录删除日志(Rich Text 编辑器场景)
  • 阻止用户剪切某些不可删除的内容

paste 事件最常见的用途

  • 过滤非法字符或敏感词
  • 限制粘贴内容的格式(比如只允许粘贴纯文本,不允许带格式)
  • 对粘贴的图片做预处理

一个实用的"只允许粘贴纯文本"方案

富文本编辑场景里,用户从 Word 复制一段带格式文字粘贴进来,往往会连样式一起粘进来,把编辑区弄乱。用paste事件可以优雅解决这个问题:

document.querySelector('#richEditor').addEventListener('paste',function(event){event.preventDefault();// 只取纯文本,丢弃 HTML 格式constplainText=event.clipboardData.getData('text/plain');document.execCommand('insertText',false,plainText);});

这个模式很常见,理解它比记住一堆 API 更有价值。

踩坑记录

坑:paste 事件里用clipboardData.setData()无效

paste事件里,event.clipboardData是只读的,调用setData()不会生效。如果需要修改粘贴内容,要先preventDefault(),然后自己用document.execCommand('insertText', ...)或 Selection API 手动插入内容。

坑:copy事件里的clipboardDatanavigator.clipboard是两套机制

事件里的event.clipboardData是同步的,只在事件处理函数执行期间有效。
navigator.clipboard(上一篇讲的那套)是异步的 Promise API。
两套机制不要混用,在同一个事件处理函数里用event.clipboardData就够了。

写在最后

剪贴板事件这块逻辑清晰,copy/cut/paste三个事件,配合event.clipboardDatapreventDefault(),能实现大多数业务需求。

下一篇会讲 Web 组件的copyOptions属性——这是 ArkTS 层的能力,可以在框架层面控制 Web 内容是否允许被复制,比 H5 事件层面的控制更彻底。