20行代码封装复制到剪贴板函数:copyToClipboard
本文由 小茗同学 发表于 2024-02-29 浏览(564)
最后修改 2024-03-01 标签:剪贴板 clipboard

一直非常不喜欢类似clipboardjs的使用方式(至于依赖flash的ZeroClipboard.js那就更不推荐了),和DOM耦合太重,使用起来非常不方便:

<button class="btn" data-clipboard-text="Just because you can doesn't mean you should — clipboard.js">
	Copy to clipboard
</button>
<script>
// 如果是SPA页面,切换页面时还需要调用 clipboard.destroy() ,否则会出现重复触发成功的问题
var clipboard = new ClipboardJS('.btn');

clipboard.on('success', function(e) {
	console.info('Action:', e.action);
	console.info('Text:', e.text);
	console.info('Trigger:', e.trigger);

	e.clearSelection();
});

clipboard.on('error', function(e) {
	console.error('Action:', e.action);
	console.error('Trigger:', e.trigger);
});
</script>

其实复制剪贴板最简单1行代码navigator.clipboard.writeText就可以实现,兼容性好的6行代码也足够了,所以封装了一个更简单、更易使用的copyToClipboard函数,可以直接替代clipboardjs

/**
 * 复制一段文本到剪贴板,如果失败会抛出异常,推荐使用姿势:
 * await copyToClipboard('要复制的文本', message => alert(`复制到剪贴板失败:${message}`));
 * alert('复制到剪贴板成功!');
 * @param {*} text 要复制的文本
 * @param {*} onFailure 失败回调,接受一个 message 参数
 * @param {*} supportSilent 是否支持后台静默复制,如果是则优先采用 execCommand
 * @returns
 */
function copyToClipboard(text, onFailure, supportSilent) {
	if (!text) {
		throw new Error('text can not be empty.');
	}
	onFailure = onFailure || (msg => console.error(`复制到剪贴板失败:${msg || ''}`));
	// 优先采用现代化API
	if (navigator.clipboard && !supportSilent) {
		// 注意 writeText API 要求:文档被激活 & 页面已启用HTTPS
		return navigator.clipboard.writeText(text).catch(e => {
			onFailure(e.message);
			throw e;
		});
	}
	// execCommand 原本是一个同步API,这里为了和 writeText 保持一致统一包成proimse
	return new Promise((resolve, reject) => {
		const input = document.createElement('input');
		input.value = text;
		input.style.cssText = 'position:fixed;left:0;top:0;opacity:0;';
		document.body.appendChild(input);
		input.select();
		try {
			if (document.execCommand('copy')) {
				resolve();
			} else {
				const message = "Failed to execute 'document.execCommand'.";
				onFailure(message);
				reject(new Error(message));
			}
		} catch (e) {
			onFailure(e.message);
			reject(e);
		} finally {
			document.body.removeChild(input);
		}
	});
}

使用方法:

// 如果复制失败不会继续往后执行
await copyToClipboard('要复制的文本', message => alert(`复制到剪贴板失败:${message}`));
alert('复制到剪贴板成功!');