前言
因为需求可能需要频繁发送验证码,文本复制等等的,将这些封装成指令使用是最方便的,自己记个笔记,方便以后要用或者新项目搭建时的时候,c+v大法(手动狗头)
节流指令 v-throttle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
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: NodeJS.Timeout | 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;
|
防抖指令 v-debounce
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
|
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: NodeJS.Timeout | 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;
|
长按指令 v-longpress
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
import type { Directive, DirectiveBinding } from "vue";
const directive: Directive = { mounted(el: HTMLElement, binding: DirectiveBinding) { if (typeof binding.value !== "function") { throw "callback must be a function"; } let pressTimer: any = null; const start = (e: any) => { if (e.button) { if (e.type === "click" && e.button !== 0) { return; } } if (pressTimer === null) { pressTimer = setTimeout(() => { handler(e); }, 1000); } }; const cancel = () => { if (pressTimer !== null) { clearTimeout(pressTimer); pressTimer = null; } }; const handler = (e: MouseEvent | TouchEvent) => { binding.value(e); }; el.addEventListener("mousedown", start); el.addEventListener("touchstart", start); el.addEventListener("click", cancel); el.addEventListener("mouseout", cancel); el.addEventListener("touchend", cancel); el.addEventListener("touchcancel", cancel); } };
export default directive;
|
拖拽指令 v-draggable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
import type { Directive } from "vue"; interface ElType extends HTMLElement { parentNode: any; } const draggable: Directive = { mounted: function (el: ElType) { el.style.cursor = "move"; el.style.position = "absolute"; el.onmousedown = function (e) { let disX = e.pageX - el.offsetLeft; let disY = e.pageY - el.offsetTop; document.onmousemove = function (e) { let x = e.pageX - disX; let y = e.pageY - disY; let maxX = el.parentNode.offsetWidth - el.offsetWidth; let maxY = el.parentNode.offsetHeight - el.offsetHeight; if (x < 0) { x = 0; } else if (x > maxX) { x = maxX; }
if (y < 0) { y = 0; } else if (y > maxY) { y = maxY; } el.style.left = x + "px"; el.style.top = y + "px"; }; document.onmouseup = function () { document.onmousemove = document.onmouseup = null; }; }; } }; export default draggable;
|
复制指令 v-copy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
import type { Directive, DirectiveBinding } from "vue"; import { Toast } from 'vant'; 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__); } };
function handleClick(this: any) { const input = document.createElement("input"); input.value = this.copyData.toLocaleString(); document.body.appendChild(input); input.select(); document.execCommand("Copy"); document.body.removeChild(input); Toast({ type: 'success', message: '复制成功', }) }
export default copy;
|
全局注册所有自定义指令
directivesIndex.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { App } from "vue"; import copy from "./modules/copy"; import draggable from "./modules/draggable"; import debounce from "./modules/debounce"; import throttle from "./modules/throttle"; import longpress from "./modules/longpress";
const directivesList: any = { copy, draggable, debounce, throttle, longpress };
const directives = { install: function (app: App<Element>) { Object.keys(directivesList).forEach(key => { app.directive(key, directivesList[key]); }); } };
export default directives;
|
在mian.ts引入并使用
1 2 3 4 5
| import directivesIndex from 'directivesIndex.ts的路径'
app.use(router).use(piniaStore).use(directivesIndex).mount('#app')
|