vue3 + ts 自定义指令 防抖指令,节流指令,复制指令
-
本文使用了
element-ui ,
element-plus 官网 -
源文件
https://admin.spicyboy.cn/#/directives/debounceDirect
-
新建
copy.ts
文件 (复制指令)
import type { Directive, DirectiveBinding } from "vue";
import { ElMessage } from "element-plus";
interface ElType extends HTMLElement {
copyData: string | number;
__handleClick__: any;
}
const copy: Directive = {
mounted(el: ElType, binding: DirectiveBinding) {
el.copyData = binding.value;
el.addEventListener("click", handleClick);
},
updated(el: ElType, binding: DirectiveBinding) {
el.copyData = binding.value;
},
beforeUnmount(el: ElType) {
el.removeEventListener("click", el.__handleClick__);
}
};
async function handleClick(this: any) {
try {
await navigator.clipboard.writeText(this.copyData);
} catch (err) {
console.error('复制失败');
}
ElMessage({
type: "success",
message: "复制成功"
});
}
export default copy;
- 新建
debounce.ts
文件 (防抖指令)
import type { Directive, DirectiveBinding } from "vue";
interface ElType extends HTMLElement {
__handleClick__: () => any;
}
const debounce: Directive = {
mounted(el: ElType, binding: DirectiveBinding) {
if (typeof binding.value !== "function") {
throw "callback must be a function";
}
let timer: number | null = null;
el.__handleClick__ = function () {
if (timer) {
clearInterval(timer);
}
timer = setTimeout(() => {
binding.value();
}, 500);
};
el.addEventListener("click", el.__handleClick__);
},
beforeUnmount(el: ElType) {
el.removeEventListener("click", el.__handleClick__);
}
};
export default debounce;
- 新建
throttle.ts
文件 (节流指令)
import type { Directive, DirectiveBinding } from "vue";
interface ElType extends HTMLElement {
__handleClick__: () => any;
disabled: boolean;
}
const throttle: Directive = {
mounted(el: ElType, binding: DirectiveBinding) {
if (typeof binding.value !== "function") {
throw "callback must be a function";
}
let timer: number | null = null;
el.__handleClick__ = function () {
if (timer) {
clearTimeout(timer);
}
if (!el.disabled) {
el.disabled = true;
binding.value();
timer = setTimeout(() => {
el.disabled = false;
}, 1000);
}
};
el.addEventListener("click", el.__handleClick__);
},
beforeUnmount(el: ElType) {
el.removeEventListener("click", el.__handleClick__);
}
};
export default throttle;
- 新建
index.ts
文件
import { App, Directive } from "vue";
import copy from "./modules/copy";
import debounce from "./modules/debounce";
import throttle from "./modules/throttle";
const directivesList: { [key: string]: Directive } = {
copy,
debounce,
throttle,
};
const directives = {
install: function (app: App<Element>) {
Object.keys(directivesList).forEach(key => {
app.directive(key, directivesList[key]);
});
}
};
export default directives;
- 在‘
main.ts
中引入index 文件
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import directives from "@/components/directives/index"; // 在此处引入指令
const app = createApp(App)
app.use(store)
app.use(directives) // 注册
app.use(router)
app.use(ElementPlus)
app.mount("#app");
- 指令使用
<template>
<div class="card content-box" style="margin-top:30px">
<span class="text">防抖指令</span>
<el-button v-debounce="debounceClick" type="primary">
防抖按钮 (0.5秒后执行)
</el-button>
</div>
<div class="card content-box" style="margin-top:30px">
<span class="text">节流指令</span>
<el-button v-throttle="throttleClick" type="primary">
节流按钮 (每隔1S秒后执行)
</el-button>
</div>
<div style="margin-top:30px">
<el-button v-copy="message">复制指令</el-button>
</div>
</template>
<script setup lang="ts" name="debounceDirect">
import { ElMessage } from "element-plus";
import { ref } from "vue";
const message = ref('这是复制指令')
const debounceClick = () => {
console.log(11111111111);
ElMessage.success("我是防抖按钮触发的事件");
};
const throttleClick = () => {
console.log(2222222222222);
ElMessage.success("我是节流按钮触发的事件");
};
</script>
- 搞定!