Vue.js

Vue3 CompositionAPIでクリップボードにコピーする方法

Vue3 CompositionAPIでクリップボードにコピーする方法を紹介します。標準のnavigator.clipboard.writeText()で済ませる最短の書き方と、clipboard.js・vue-clipboard3を使う方法をまとめました。

この記事の目次
  1. Vue3 CompositionAPIでクリップボードにコピーする方法
  2. ライブラリなしで実装する場合(navigator.clipboard)
  3. clipboard.jsを使う場合
  4. Clipboard.jsをインストール
  5. composables/useClipboardファイルを作成
  6. Vueコンポーネントで使用
  7. vue-clipboard3を使う方法

Vue3 CompositionAPIでクリップボードにコピーする方法を紹介します。

結論から書くと、テキストをコピーするだけなら、ライブラリを入れずにブラウザ標準のnavigator.clipboard.writeText()を呼ぶのが最短です。HTTPS(またはlocalhost)で、クリックなどユーザー操作の中から呼ぶ必要があります。古いブラウザへの対応や細かな制御が必要な場合は、この記事で紹介するclipboard.jsやvue-clipboard3を使います。

Vue3 CompositionAPIでクリップボードにコピーする方法

こちらの記事がとても参考になります。

ライブラリなしで実装する場合(navigator.clipboard)

現在のブラウザでは、Clipboard APIのwriteText()だけでコピーできます。Promiseを返すので、async/awaittry/catchで成否を受け取ります。

import { ref } from 'vue'

export default {
  setup() {
    const text = ref('ここにコピーしたいテキスト')
    const copied = ref(false)

    const copy = async () => {
      try {
        await navigator.clipboard.writeText(text.value)
        copied.value = true
      } catch (e) {
        console.error(e)
      }
    }
    return { text, copied, copy }
  }
}

navigator.clipboardはHTTPSかlocalhost以外ではundefinedになります。HTTPのテスト環境でコピーできないときは、まずここを疑ってください。

clipboard.jsを使う場合

ここからは、Clipboard APIが使えない環境もカバーしたいときの方法です。

Clipboard.jsをインストール

$ yarn add clipboard
$ yarn add --dev @types/clipboard

JavaScriptで使うなら1行目だけ、TypeScriptで使うなら2行とも実行します。

composables/useClipboardファイルを作成

srcフォルダにcomposablesフォルダを作成し、その中にuseClipboard.(ts/js)ファイルを作成します。

TypeScriptの場合

VueのCompositionAPIにTypeScriptを使っている場合は、上の記事にそのまま沿えば実装できます。

JavaScriptの場合

TypeScriptの部分を削除していけばOKです。

import Clipboard from 'clipboard'

export default (opts) => {
  // default appendToBody true
  const appendToBody = opts?.appendToBody === undefined ? true : opts.appendToBody
  return {
    toClipboard(text, container) {
      return new Promise((resolve, reject) => {
        // fakeエレメントの作成
        const fakeEl = document.createElement('button')
        // Clipboard.jsの新規作成
        const clipboard = new Clipboard(fakeEl, {
          text: () => text,
          action: () => 'copy',
          container: container !== undefined ? container : document.body
        })
        clipboard.on('success', (e) => {
          clipboard.destroy()
          resolve(e)
        })
        clipboard.on('error', (e) => {
          clipboard.destroy()
          reject(e)
        })

        // 要素のマウスクリックイベントを発生
        fakeEl.click()
        // bodyから取り除く
        if (appendToBody) document.body.removeChild(fakeEl)
      })
    }
  }
}

Vueコンポーネントで使用

template


<button @click="copy"><i class='bx bxs-copy'></i></button>

上ではboxiconsを使っていますが、iタグ部分は何でも大丈夫です。

script

import useClipboard from '@/composables/useClipboard'
export default {
  setup() {
    const { toClipboard } = useClipboard()
    const text = 'ここにコピーしたいテキスト'

    const copy = async () => {
      try {
        await toClipboard(text)
        console.log('Copied to clipboard')
      } catch (e) {
        console.error(e)
      }
    }
    return { copy, text }
  }
}

textrefにすれば、入力欄の内容など動的な値もコピーできます。

Composition APIでCannot read property 'util' of undefinedのようなエラーが出る場合は、Vueのcomposition APIのエラー:Cannot read property ‘util’ of undefinedを確認してください。

スポンサーリンク

vue-clipboard3を使う方法

上の記事の人が作成したオープンソースのvue-clipboard3があります。

これを使うとより簡単に実装できます。なお、どの方法でも実際にコピーできるのはユーザー操作の直後だけです。ページ読み込み時に自動でコピーする処理は、ブラウザ側でブロックされます。

スポンサーリンク