Vue3 CompositionAPIでクリップボードにコピーする方法を紹介します。
結論から書くと、テキストをコピーするだけなら、ライブラリを入れずにブラウザ標準のnavigator.clipboard.writeText()を呼ぶのが最短です。HTTPS(またはlocalhost)で、クリックなどユーザー操作の中から呼ぶ必要があります。古いブラウザへの対応や細かな制御が必要な場合は、この記事で紹介するclipboard.jsやvue-clipboard3を使います。
Vue3 CompositionAPIでクリップボードにコピーする方法
こちらの記事がとても参考になります。
ライブラリなしで実装する場合(navigator.clipboard)
現在のブラウザでは、Clipboard APIのwriteText()だけでコピーできます。Promiseを返すので、async/awaitとtry/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 }
}
}
textをrefにすれば、入力欄の内容など動的な値もコピーできます。
Composition APIでCannot read property 'util' of undefinedのようなエラーが出る場合は、Vueのcomposition APIのエラー:Cannot read property ‘util’ of undefinedを確認してください。
vue-clipboard3を使う方法
上の記事の人が作成したオープンソースのvue-clipboard3があります。
これを使うとより簡単に実装できます。なお、どの方法でも実際にコピーできるのはユーザー操作の直後だけです。ページ読み込み時に自動でコピーする処理は、ブラウザ側でブロックされます。