JavaScript实现:复制文本到剪贴板

421 阅读2分钟

最近在实现点击复制标签文本内容时,踩了一点小坑,记录下来分享给大家,如何实现一键点击复制功能,以及避免踩坑。

方法介绍

第一种是document.execCommand()。

exeCommand方法是document提供的API,该命令允许运行命令来操作可编辑内容区域的元素,我们使用到的命令是copy

具体代码如下:

function copyTextByExecCommand (text) {
  let textArea = document.createElement('textArea')
  textArea.value = text
  textArea.style.display = "none"
  document.body.appendChild(textArea)
  textArea.focus()
  textArea.select()

  try {
    let success = document.execCommand('copy')
    let msg = success ? '已复制文本到剪切板' : '复制文本失败'
    alert(msg)
  } catch (err) {
    alert(`复制文本时出现异常: ${err}`)
  }
  document.body.removeChild(textArea)
}

第二种方法是navigator.clipboard。

navigator.clipboard是浏览器提供的API,在用户授予权限下,能够提供系统剪贴板的读写访问。因此我们可以使用navigator.clipboard.writeText()方法将文本写入到操作系统的剪贴板(另外navigator.clipboard.write()可以写入任意数据到剪贴板中)。

代码如下:

function copyTextByClipboard (text) {
  navigator.clipboard.writeText(text)
    .then(() => {
      alert('已复制文本到剪切板')
    })
}

但这样使用此API,会有拷贝失败的风险。 原因是此API要求用户授予相应权限之后,或要求网站具有一定的安全性,如HTTPS或localhost。 以上代码,在https或localhost下能够成功复制,在http下却无法复制。

建议结合方法一,对http进行兼容。因为在HTTP协议下使用获取授权的方法来使用API,会直接得到拒绝,而不是弹出预期的弹窗,来询问用户授权。

获取授权的方法如下:

navigator.permissions.query({ name: 'clipboard-write' })
  .then((result) => {
    // 可能是 'granted', 'denied' or 'prompt'
    if (result.state === 'granted') {
	  copyTextByClipboard(text)
	} else if (result.state === 'prompt') {
	  console.log('prompt')
	} else {
	  console.log('reject')
	}
  })

运行结果:

使用execCommand进行兼容,代码实现如下:

function copyText (text) {
  if (typeof(navigator.clipboard) == 'undefined') {
    copyTextByExecCommand(text)
    return
  }
  copyTextByClipboard(text)
}