Vue2 同步/异步写入剪切板

1,293 阅读1分钟

方式

  • document.execCommand
  • navigator.clipboard
  • Clipboard.js
  • vue2-clipboard

document.execCommand

使用方式

<textarea ref="copyInput" :value="copyInfo" />
 this.$nextTick(() => { // 为防止dom未加载完,包裹在$nextTick里
   const copyInput = this.$refs.copyInput
   copyInput.select()
   document.execCommand('copy')
   this.$message.success('复制成功,可粘贴查看')
})

问题

document.execCommand不同浏览器以及浏览器的不同版本兼容性较差,甚至会出现使用时既不报错也没有效果的现象,而且现在已经允许浏览器自行砍掉这个api,不推荐使用。

navigator.clipbard

使用方式

navigator.clipboard.writeText(this.copyInfo).then(() => {
  this.$message.success('复制成功,可粘贴查看')
}).catch(err => {
  this.$message.err('复制失败,', JSON.stringify(err))
})

问题

navigator.clipboard浏览器兼容性较好,支持异步复制,但对安全性要求较高,仅支持本地使用和https的网站使用,http网站禁用

Clipboard.js

使用

npm或者yarn安装clipboard.js

npm i clipboard.js
<div id="LoadSql" :data-clipboard-text="copyInfo" @click.stop="copyInfo()">点我复制</div>
// 引入
import Clipboard from 'clipboard.js'

// data()中存储初始化复制按钮事件
copyBtn: null

// mounted()中注册
this.copyBtn = new Clipboard(#LoadSql)

// methods
copyInfo(){
  const clipboard = new Clipboard('#LoadSql')
  clipboard.on('success', e => {
    this.$message.success('复制成功,可粘贴查看')
    // 释放内存
    clipboard.destroy()
  })
  clipboard.on('error', e => {
    // 不支持复制
    this.$message.warning('该浏览器不支持自动复制')
    // 释放内存
    clipboard.destroy()
  })
}

问题

new Clipboard中传入的对象只能是原始Dom元素,传入封装的组建会报错。 旧版本的浏览器,比如chrome69等不支持异步使用。 第二次点击才能正常复制,相当于第n次点击复制的是(n-1)次点击的内容

vue-clipboard2

vue-clipboard2是基于clipboard.js的一个封装,并提供了多个自定义指令

使用

  • 普通使用
        this.$copyText(this.copyInfo).then(
          function(e) {
            alert('复制成功')
          },
          function(e) {
            console.log(e)
            alert('复制失败')
          }
        )
  • 自定义指令
                <div
                  v-clipboard:copy="copyInfo"
                  v-clipboard:success="onSuccess"
                  v-clipboard:error="onFailed"
                  @click.stop.prevent="copyInfo"
                >
                  点我复制
                </div>

问题

支持异步使用,但需手动触发按钮click事件,也有clipboard.js的n-1次的通病。

解决

搭配Clipboard.js,在dom元素上添加@mouseenter.once调用一遍函数与复制,相当于第1次,后续再使用点击调用时就正常了

                <div
                  v-clipboard:copy="copyInfo"
                  v-clipboard:success="onSuccess"
                  v-clipboard:error="onFailed"
                  @mouseenter.once="copyInfo($event)"
                  @click.stop.prevent="copyInfo"
                >
                  点我复制
                </div>
    async copyInfo(event) {
      const params = {}
      this.dataLoading = true
      try {
        const res = await getFun(params)
        this.copyInfo = res.data.content 
      } catch (err) {
        this.$message.err(err)
      }
      if (isMouseEnter) {
        setTimeout(() => {
          const clipbard = new Clipboard(event.target)
          clipbard.on('success', e => {
            // 释放内存
            clipbard.destroy()
          })
          clipbard.on('error', e => {
          // 释放内存
            clipbard.destroy()
          })
        }, 500)
      }
    },

总结

  • 同步复制

    • document.execCommand (不推荐)
    • navigator.clipboard (仅hhtps生效)
    • clipboard.js
    • vue-clipboard2
  • 异步复制

    • navigator.clipboard (仅hhtps生效)
    • clipboard.js (低版本浏览器不生效,n-1次复制问题)
    • vue-clipboard2 (低版本浏览器不生效,n-1次复制问题)
    • vue-clipboard2自定义指令 + @mouseenter.once主动触发一次clipboard (解决问题)