必须用 document.addeventlistener('copy', handler) 统一追加版权,关键三步:preventdefault()、getselection().tostring()、setdata('text/plain', newtext),缺一不可;需兼容旧版浏览器 fallback 到 execcommand;后缀需智能判断内容类型并可配置。

document.addEventListener('copy') 是唯一可靠入口
想在用户按 Ctrl+C 或右键复制时统一追加版权,必须用 document.addEventListener('copy', handler)。其他方式(比如 oncopy 属性、给某个 <div> 单独绑定)要么作用域太窄,要么在跨元素选中时失效。
<p>关键三步必须同步执行,缺一不可:</p>
<ul>
<li>
<code>event.preventDefault() —— 不调就无法覆盖默认写入行为
window.getSelection().toString() —— 获取当前选中文本,不是 document.getSelection()(不存在)event.clipboardData.setData('text/plain', newText) —— MIME 类型只能是 'text/plain' 或 'text/html',传 'Text' 在 Firefox 会失败漏掉任一,你的版权文本就不会出现。别把 setData 扔进 setTimeout 或异步回调里——那会丢失用户手势上下文,浏览器直接忽略。
兼容旧版浏览器必须降级到 execCommand
部分 iOS Safari(≤16.4)、老版 Edge 或禁用 Clipboard API 的环境里,event.clipboardData 可能为 null,或者根本没这个属性。这时候不能硬报错,得 fallback。
降级方案本质是“伪造一次选中”:
- 创建一个
<textarea style="position: absolute; left: -9999px;"></textarea> - 设置其
value为“选中文本 + 版权后缀” - 调用
textarea.select()再执行document.execCommand('copy') - 立刻移除该
<textarea></textarea>,避免残留 DOM
注意:document.execCommand 已废弃,但目前仍是兼容性兜底的唯一可行路径;它不要求 HTTPS,也不依赖用户手势权限,但必须在事件处理函数内同步触发。
版权后缀要避开敏感内容和格式破坏
直接无脑拼接会导致代码块、URL、邮箱被污染,用户粘贴后无法使用。得先判断再决定是否添加:
- 用正则快速识别:
/^https?:\/\//i.test(text)跳过链接,/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(text)跳过邮箱 - 若原文含多个换行,版权行建议用单行分隔符(如
[来源:xxx]),避免插入空行打乱 Markdown 或代码缩进 - 后缀文案本身应可配置,别写死在代码里;推荐结构:
\n\n—— 来源:${siteName} | 禁止商用
别忘了提供关闭开关——哪怕只是个 localStorage 标志位,否则用户第一次复制就看到版权,体验极差。
别指望拦截系统级 Ctrl+C 的“行为”,只能改写“内容”
监听 copy 事件不是为了阻止复制动作本身(那做不到),而是为了在内容写入剪贴板前做最后一道修改。系统快捷键触发的复制一样会走这个事件流,所以你依然能改写内容。
但以下情况你完全无能为力:
- 用户手动打开系统剪贴板历史(如 Windows 10+ 的 Win+V),从那里复制旧内容
- 用第三方剪贴板管理工具(如 Ditto、Paste)绕过浏览器 API
- 截图 OCR 提取文字
真正容易被忽略的是:移动端 WKWebView 基本不触发 copy 事件,iOS Safari 对 clipboardData 支持不稳定——如果你的页面主要面向手机用户,这个功能大概率形同虚设。











