When I was refactoring an old project with VUe3 recently, I found that vuE-Clipboard3 only provided a composite API, and the instructions in v2 version seemed to be missing. It was a good time to think about how to package the instructions in the project library.
Train of thought
- Create a separate folder for the instruction set
- The index.ts export provides a Plugin object in which all directives are installed collectively
The file structure is as follows:
The contents of index.ts are also easier to implement:
//index.ts
import { ObjectDirective, App, Plugin } from "vue";
// Custom directives can reference more than one
import vClipboard from "./vClipboard";
// Define the instruction option category
export interface DirectiveOption {
name: string; // Directive name
options: ObjectDirective; // Command options
}
// Build the instruction set
const directives: DirectiveOption[] = [vClipboard];
export default <Plugin>{
install: (app: App) = > {
// Install instruction set
directives.forEach((item) = >{ app.directive(item.name, item.options); }); }};Copy the code
- We can export each directive individually if we want to use on-demand references
VClipboard3 instruction implementation
- The original vclipboard provides the following commands: V-CLIpboard :copy, V-Clipboard :success, and V-Clipboard :error
- The VUe3 directive also supports dynamic instruction parameters
- We only need to deal with these instruction parameters
- Copy accepts the value that you want to copy
- Success accepts a successful callback from COPY
- Error accepts a copy failure callback
- Our directive supports copy
Based on the above code implementation is as follows:
// vClipboard.ts
import { DirectiveOption } from "./index";
// Vue-Clipboard3 composition API
import useClipboard from "vue-clipboard3";
const { toClipboard } = useClipboard();
export default <DirectiveOption>{
name: "clipboard".options: {
/ / a mount
mounted(el, binding) {
// binding.arg is a dynamic directive parameter
// Since directives are responsive, we need to have a "global" object, so we use el itself instead of wasting resources with other objects
// Bind copy's value success callback, failure callback and click event to el for easy operation during update and uninstall
switch (binding.arg) {
case "copy":
/ / copy
el.clipValue = binding.value;
/ / click event
el.clipCopy = function () {
toClipboard(el.clipValue)
.then(result= > {
el.clipSuccess && el.clipSuccess(result);
})
.catch(err= > {
el.clipError && el.clipError(err);
});
};
// Bind the click event
el.addEventListener("click", el.clipCopy);
break;
case "success":
// Successful callback
el.clipSuccess = binding.value;
break;
case "error":
// Failed callback
el.clipError = binding.value;
break; }},// Change the corresponding value
updated(el, binding) {
switch (binding.arg) {
case "copy":
el.clipValue = binding.value;
break;
case "success":
el.clipSuccess = binding.value;
break;
case "error":
el.clipError = binding.value;
break; }},// Remove the click event to remove the corresponding custom property
unmounted(el, binding) {
switch (binding.arg) {
case "copy":
el.removeEventListener("click", el.clipCopy);
delete el.clipValue;
delete el.clipCopy;
break;
case "success":
delete el.clipSuccess;
break;
case "error":
delete el.clipError;
break; ,}}}};Copy the code
use
- Global mount
import { createApp } from 'vue'
import DirectiveExtensions from './directive'
import App from './App.vue'
const app = createApp(App)
app.use(DirectiveExtensions)
app.mount('#app')
Copy the code
- Components use
<template>
<section class="test-component-copy">
<div
class="btn-copy"
v-clipboard:copy="content"
v-clipboard:success="Copy"
v-clipboard:error="Error"
>{{ content }}</div>
</div>
</section>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { toast } from '.. /.. /.. /components/toast/useToast'
const content = ref("Please manually enter what you want to copy in the code!")
function Copy() {
toast('Content copied to clipboard! ');
}
function Error() {
toast('Copy error! ');
}
</script>
Copy the code
Granularity and location of instruction encapsulation
- Vue3 provides a way to customize instructions in setup
- So we need a tradeoff, generally generic instructions that we recommend going straight into the instruction set
- If the instructions are not generic, you can customize them in Setup alone, but my feeling is that if the instructions are not generic, then they don’t need to exist