这篇博文主要分享如何在一个传统的html中,通过通过引入js方式使用vue功能和vue复制组件。
项目是一个传统的前后端在一起的项目,前端框架使用的一些前端组件库是通过在html中引入bootstrap,vue 等JS实现。
无法使用包管理器,不支持import和export等语法,现在要求在这样的背景下,实现一键复制功能。
我们知道在支持包管理器安装的vue项目中可以这样使用,有两种用法。
但是很显然第二种v-clipboard:copy="inputData"
使用方式更加优雅。
<template>
<div class="app-container">
<el-tabs v-model="activeName">
<el-tab-pane label="use clipboard directly" name="directly">
<el-input
v-model="inputData" placeholder="Please input"
style="width:400px;max-width:100%;" />
<el-button type="primary"
icon="el-icon-document"
@click="handleCopy(inputData,$event)"
>
copy
el-button>
el-tab-pane>
<el-tab-pane label="use clipboard by v-directive" name="v-directive">
<el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;" />
<el-button
v-clipboard:copy="inputData"
v-clipboard:success="clipboardSuccess"
type="primary" icon="el-icon-document">
copy
el-button>
el-tab-pane>
el-tabs>
div>
template>
<script>
import clip from '@/utils/clipboard' // use clipboard directly
import clipboard from '@/directive/clipboard' // use clipboard by v-directive
export default {
name: 'ClipboardDemo',
directives: {
clipboard
},
data() {
return {
activeName: 'directly',
inputData: 'https://github.com/PanJiaChen/vue-element-admin'
}
},
methods: {
handleCopy(text, event) {
clip(text, event)
},
clipboardSuccess() {
this.$message({
message: 'Copy successfully',
type: 'success',
duration: 1500
})
}
}
}
script>
- 详细示例参见:https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/clipboard/index.vue
那么在传统的html中引入js方式使用,又该如何改造呢?
封装简化下
clipboard_plugin_v1.js
// 定义自定义指令对象
const clipboardDirective = {
// 在 bind 钩子中初始化 Clipboard.js 实例
bind(el, binding) {
const clipboard = new ClipboardJS(el, {
text: () => binding.value,
});
clipboard.on('success', (e) => {
e.clearSelection();
// 触发成功复制事件,您可以在这里添加自定义处理逻辑
el.dispatchEvent(new Event('clipboard-success'));
});
clipboard.on('error', (e) => {
// 触发复制失败事件,您可以在这里添加自定义处理逻辑
el.dispatchEvent(new Event('clipboard-error'));
});
// 将 Clipboard.js 实例绑定到元素上以便后续销毁
el._clipboard = clipboard;
},
// 在 unbind 钩子中销毁 Clipboard.js 实例
unbind(el) {
const clipboard = el._clipboard;
if (clipboard) {
clipboard.destroy();
delete el._clipboard;
}
},
};
// 注册自定义指令
Vue.directive('clipboard', clipboardDirective);
html中使用示例
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用自定义 Clipboard 指令title>
head>
<body>
<div id="app">
<el-button
@click="copyText(textToCopy)"
id="clipboardBtn"
type="primary"
icon="el-icon-document"
>
复制
el-button>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js">script>
<script src="../assets/js/clipboard/clipboard_plugin_v1.js">script>
<script>
// 创建 Vue 实例
new Vue({
el: '#app',
directives: { clipboardDirective },
data: {
textToCopy: '这是要复制的文本',
clipboardInstance: null,
},
methods: {
copyText(textToCopy) {
let vm = this;
if (vm.clipboardInstance) {
vm.clipboardInstance.destroy(); // 销毁旧的 clipboard 实例
}
// 在此处将要复制的文本设置为传递的参数
vm.clipboardInstance = new ClipboardJS('#clipboardBtn', {
text: () => textToCopy
});
vm.clipboardInstance.on('success', (e) => {
e.clearSelection();
vm.$message({
message: '文本已成功复制到剪贴板!',
type: 'success',
duration: 1500
})
});
vm.clipboardInstance.on('error', (e) => {
e.clearSelection();
vm.$message({
message: '复制操作失败,请手动复制文本!',
type: 'error',
duration: 1500
})
});
// 在调用 copyToClipboard 方法时自动启动剪贴板复制操作,因此用户不需要手动单击按钮来复制文本。
//vm.clipboardInstance.onClick({ currentTarget: document.querySelector('#clipboardBtn') });
},
},
});
script>
body>
html>
为了简化可以使用类似 v-clipboard:copy
语法,这里我们除了引入剪切板js库之外,还需要封装下指令到一个js中。
因为只有封装后我们才能使用directives: { clipboardDirectiveV2 },
这种语法来简化使用。
clipboard_plugin_v2.js
// clipboard_plugin_v2.js
// Inspired by https://github.com/Inndy/vue-clipboard2
const clipboardDirectiveV2 = {
bind(el, binding) {
if (binding.arg === 'success') {
el._v_clipboard_success = binding.value
} else if (binding.arg === 'error') {
el._v_clipboard_error = binding.value
} else {
const clipboard = new ClipboardJS(el, {
text: () => binding.value,
action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
});
clipboard.on('success', e => {
const callback = el._v_clipboard_success
callback && callback(e) // eslint-disable-line
})
clipboard.on('error', e => {
const callback = el._v_clipboard_error
callback && callback(e) // eslint-disable-line
})
el._v_clipboard = clipboard
}
},
update(el, binding) {
if (binding.arg === 'success') {
el._v_clipboard_success = binding.value
} else if (binding.arg === 'error') {
el._v_clipboard_error = binding.value
} else {
el._v_clipboard.text = function() { return binding.value }
el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
}
},
unbind(el, binding) {
if (binding.arg === 'success') {
delete el._v_clipboard_success
} else if (binding.arg === 'error') {
delete el._v_clipboard_error
} else {
el._v_clipboard.destroy()
delete el._v_clipboard
}
}
}
// 注册自定义指令
Vue.directive('clipboard', clipboardDirectiveV2);
然后在html中调用
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用自定义 Clipboard 指令title>
head>
<body>
<div id="app">
<button
v-clipboard:copy="textToCopy"
@clipboard-success="handleCopySuccess"
@clipboard-error="handleCopyError">复制button>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]">script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/clipboard.min.js">script>
<script src="../assets/js/clipboard/clipboard_plugin_v2.js">script>
<script>
// 创建 Vue 实例
new Vue({
el: '#app',
directives: { clipboardDirectiveV2 },
data: {
textToCopy: '这是要复制的文本',
},
methods: {
handleCopySuccess() {
// 复制成功时的处理逻辑
alert('文本已成功复制到剪贴板!');
},
handleCopyError() {
// 复制失败时的处理逻辑
alert('复制操作失败,请手动复制文本!');
},
},
});
script>
body>
html>