外观
Clipboard
Clipboard 提供一层轻量的文本复制 API,用来统一 browser / WebView 应用里常见的复制到剪贴板逻辑。
它解决的是运行时基础问题:优先使用原生 Clipboard API,并在受限 WebView 或不支持原生 API 时尝试兼容 fallback。它不负责 toast、埋点、按钮状态、复制内容序列化、读取剪贴板、剪切或粘贴输入规则。
适合场景
| 场景 | 推荐入口 | 说明 |
|---|---|---|
| 复制分享链接 | clipboard.writeText | 例如新闻详情、活动页、邀请链接。 |
| 复制调试日志 | clipboard.writeText | 业务先把日志格式化成字符串,再传给 runtime。 |
| 复制配置或 JSON | clipboard.writeText | 对象序列化由业务负责。 |
| 输入框粘贴处理 | 组件自己的 paste 事件 | 需要结合 selection、readonly 和业务规则。 |
基础使用
ts
import { createClipboard } from '@freenotes/web-runtime';
const clipboard = createClipboard();
try {
await clipboard.writeText('hello');
showToast('已复制');
} catch (error) {
showToast('复制失败,请稍后重试');
reportCopyError(error);
}writeText 返回 Promise<void>:某种写入策略报告成功时 resolve,所有策略失败时 reject ClipboardError。
错误的 kind 区分 invalid-input、unavailable 和 write-failed;code 为 ERR_CLIPBOARD_*。单个策略失败时 cause 保留原始异常,多个策略失败时 cause 是按尝试顺序排列的只读异常数组。可通过根入口导入 ClipboardError 并使用 instanceof 判断。
业务应该自己决定成功失败后的 UI 反馈和业务上报。
为什么不直接导出 writeText
不提供:
ts
writeText('hello');writeText 脱离 clipboard 后语义太泛,后续容易和文件、编辑器、日志、bridge 等能力冲突。
推荐:
ts
await clipboard.writeText('hello');这个写法和原生 API 对齐:
ts
await navigator.clipboard.writeText('hello');同时也符合 runtime 的能力分组规则:
ts
createStorage('local').set('ready', true);
await createDb().open({ name: 'app', stores: { notes: { keyPath: 'id' } } });
await clipboard.writeText('hello');可用性判断
ts
const available = clipboard.isAvailable();isAvailable() 只表示当前环境看起来存在可用策略,例如 navigator.clipboard.writeText 或 document.execCommand('copy') fallback。
剪贴板写入经常依赖:
- HTTPS 或安全上下文。
- 浏览器权限。
- 用户手势,例如点击按钮。
- WebView 宿主策略。
- iOS WebKit 对选区和复制时机的限制。
因此 isAvailable() 不能保证下一次 writeText() 一定成功。最终仍应以 writeText() 的 Promise 结果为准。
兼容策略
clipboard.writeText(text) 会按下面顺序尝试:
navigator.clipboard.writeText(text)。- 临时
textarea + document.execCommand('copy')。 - 临时
contenteditable + document.execCommand('copy')。
fallback 元素会在复制后移除,并尽量恢复原来的选区和焦点。
不做什么
Clipboard 第一版不提供:
ts
clipboard.readText();
clipboard.cut();
clipboard.paste();原因是:
- 读取剪贴板涉及更强的权限和隐私约束,当前没有稳定通用场景。
- 粘贴通常来自输入框的
paste事件,需要由组件结合 selection、格式归一化和业务规则处理。 - 剪切通常由浏览器原生输入控件完成,runtime 不应接管用户编辑行为。
Clipboard 也不接管 vConsole 复制按钮这类特殊事件链路。此类问题通常需要业务在对应工具初始化时单独 patch。
API 速查
| API | 说明 |
|---|---|
clipboard.writeText(text) | 尽力把文本写入系统剪贴板。 |
clipboard.isAvailable() | 判断当前环境是否看起来存在复制策略。 |