mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-07 17:07:19 +08:00
feat: 添加长按指令及使用示例,该长按指令支持自定义时长的持续回调 (#620)
This commit is contained in:
parent
5f71e0aad7
commit
b8200125dc
@ -68,7 +68,7 @@ menus:
|
|||||||
hsguide: Guide
|
hsguide: Guide
|
||||||
hsAble: Able
|
hsAble: Able
|
||||||
hsMenuTree: Menu Tree
|
hsMenuTree: Menu Tree
|
||||||
hsOptimize: Debounce、Throttle、Copy Directives
|
hsOptimize: Debounce、Throttle、Copy、Longpress Directives
|
||||||
hsWatermark: Water Mark
|
hsWatermark: Water Mark
|
||||||
hsPrint: Print
|
hsPrint: Print
|
||||||
hsDownload: Download
|
hsDownload: Download
|
||||||
|
@ -68,7 +68,7 @@ menus:
|
|||||||
hsguide: 引导页
|
hsguide: 引导页
|
||||||
hsAble: 功能
|
hsAble: 功能
|
||||||
hsMenuTree: 菜单树结构
|
hsMenuTree: 菜单树结构
|
||||||
hsOptimize: 防抖、截流、复制指令
|
hsOptimize: 防抖、截流、复制、长按指令
|
||||||
hsWatermark: 水印
|
hsWatermark: 水印
|
||||||
hsPrint: 打印
|
hsPrint: 打印
|
||||||
hsDownload: 下载
|
hsDownload: 下载
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { hasAuth } from "@/router/utils";
|
import { hasAuth } from "@/router/utils";
|
||||||
import { Directive, type DirectiveBinding } from "vue";
|
import type { Directive, DirectiveBinding } from "vue";
|
||||||
|
|
||||||
export const auth: Directive = {
|
export const auth: Directive = {
|
||||||
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { useEventListener } from "@vueuse/core";
|
import { useEventListener } from "@vueuse/core";
|
||||||
import { copyTextToClipboard } from "@pureadmin/utils";
|
import { copyTextToClipboard } from "@pureadmin/utils";
|
||||||
import { Directive, type DirectiveBinding } from "vue";
|
import type { Directive, DirectiveBinding } from "vue";
|
||||||
|
|
||||||
interface CopyEl extends HTMLElement {
|
interface CopyEl extends HTMLElement {
|
||||||
copyValue: string;
|
copyValue: string;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./auth";
|
export * from "./auth";
|
||||||
export * from "./copy";
|
export * from "./copy";
|
||||||
|
export * from "./longpress";
|
||||||
export * from "./optimize";
|
export * from "./optimize";
|
||||||
|
63
src/directives/longpress/index.ts
Normal file
63
src/directives/longpress/index.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { useEventListener } from "@vueuse/core";
|
||||||
|
import type { Directive, DirectiveBinding } from "vue";
|
||||||
|
import { subBefore, subAfter, isFunction } from "@pureadmin/utils";
|
||||||
|
|
||||||
|
export const longpress: Directive = {
|
||||||
|
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||||
|
const cb = binding.value;
|
||||||
|
if (cb && isFunction(cb)) {
|
||||||
|
let timer = null;
|
||||||
|
let interTimer = null;
|
||||||
|
let num = 500;
|
||||||
|
let interNum = null;
|
||||||
|
const isInter = binding?.arg?.includes(":") ?? false;
|
||||||
|
|
||||||
|
if (isInter) {
|
||||||
|
num = Number(subBefore(binding.arg, ":"));
|
||||||
|
interNum = Number(subAfter(binding.arg, ":"));
|
||||||
|
} else if (binding.arg) {
|
||||||
|
num = Number(binding.arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = null;
|
||||||
|
}
|
||||||
|
if (interTimer) {
|
||||||
|
clearInterval(interTimer);
|
||||||
|
interTimer = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDownInter = (ev: PointerEvent) => {
|
||||||
|
ev.preventDefault();
|
||||||
|
if (interTimer === null) {
|
||||||
|
interTimer = setInterval(() => cb(), interNum);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDown = (ev: PointerEvent) => {
|
||||||
|
clear();
|
||||||
|
ev.preventDefault();
|
||||||
|
if (timer === null) {
|
||||||
|
timer = isInter
|
||||||
|
? setTimeout(() => {
|
||||||
|
cb();
|
||||||
|
onDownInter(ev);
|
||||||
|
}, num)
|
||||||
|
: setTimeout(() => cb(), num);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Register using addEventListener on mounted, and removeEventListener automatically on unmounted
|
||||||
|
useEventListener(el, "pointerdown", onDown);
|
||||||
|
useEventListener(el, "pointerup", clear);
|
||||||
|
useEventListener(el, "pointerleave", clear);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
'[Directive: longpress]: need callback and callback must be a function! Like v-longpress="callback"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -6,7 +6,7 @@ import {
|
|||||||
throttle
|
throttle
|
||||||
} from "@pureadmin/utils";
|
} from "@pureadmin/utils";
|
||||||
import { useEventListener } from "@vueuse/core";
|
import { useEventListener } from "@vueuse/core";
|
||||||
import { Directive, type DirectiveBinding } from "vue";
|
import type { Directive, DirectiveBinding } from "vue";
|
||||||
|
|
||||||
/** 防抖(v-optimize或v-optimize:debounce)、节流(v-optimize:throttle)指令 */
|
/** 防抖(v-optimize或v-optimize:debounce)、节流(v-optimize:throttle)指令 */
|
||||||
export const optimize: Directive = {
|
export const optimize: Directive = {
|
||||||
|
@ -13,6 +13,9 @@ const searchFour = ref("");
|
|||||||
const searchFive = ref("");
|
const searchFive = ref("");
|
||||||
const searchSix = ref("copy");
|
const searchSix = ref("copy");
|
||||||
const text = ref("可复制的文本");
|
const text = ref("可复制的文本");
|
||||||
|
const long = ref(false);
|
||||||
|
const cbText = ref("");
|
||||||
|
const idx = ref(0);
|
||||||
|
|
||||||
function onInput() {
|
function onInput() {
|
||||||
message(search.value);
|
message(search.value);
|
||||||
@ -30,13 +33,30 @@ function onInputFour() {
|
|||||||
function onInputFive({ name, sex }) {
|
function onInputFive({ name, sex }) {
|
||||||
message(`${name}${sex}${searchFive.value}`);
|
message(`${name}${sex}${searchFive.value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onLongpress() {
|
||||||
|
long.value = true;
|
||||||
|
}
|
||||||
|
function onCustomLongpress() {
|
||||||
|
long.value = true;
|
||||||
|
}
|
||||||
|
function onCbLongpress() {
|
||||||
|
idx.value += 1;
|
||||||
|
long.value = true;
|
||||||
|
cbText.value = `持续回调${idx.value}次`;
|
||||||
|
}
|
||||||
|
function onReset() {
|
||||||
|
long.value = false;
|
||||||
|
cbText.value = "";
|
||||||
|
idx.value = 0;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-card shadow="never">
|
<el-card shadow="never">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<span class="font-medium">自定义防抖、截流、文本复制指令</span>
|
<span class="font-medium">自定义防抖、截流、文本复制、长按指令</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
@ -113,5 +133,24 @@ function onInputFive({ name, sex }) {
|
|||||||
文本复制指令(自定义触发事件,单击复制)
|
文本复制指令(自定义触发事件,单击复制)
|
||||||
<span v-copy:click="text" class="text-sky-500">{{ text }}</span>
|
<span v-copy:click="text" class="text-sky-500">{{ text }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-divider />
|
||||||
|
<el-space wrap>
|
||||||
|
长按指令
|
||||||
|
<el-button v-longpress="onLongpress">长按(默认500ms)</el-button>
|
||||||
|
<el-button v-longpress:1000="onCustomLongpress">
|
||||||
|
自定义长按时长(1000ms)
|
||||||
|
</el-button>
|
||||||
|
<el-button v-longpress:2000:200="onCbLongpress">
|
||||||
|
2秒后每200ms持续回调
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onReset"> 重置状态 </el-button>
|
||||||
|
<el-tag :type="long ? 'success' : 'info'" class="ml-2" size="large">
|
||||||
|
{{ long ? "当前为长按状态" : "当前非长按状态" }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-if="cbText" type="danger" class="ml-2" size="large">
|
||||||
|
{{ cbText }}
|
||||||
|
</el-tag>
|
||||||
|
</el-space>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user