mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-08 17:37:24 +08:00
Merge branch 'main' of github.com:pure-admin/vue-pure-admin into gitee
This commit is contained in:
commit
4e62edc78e
@ -68,6 +68,7 @@ menus:
|
|||||||
hsguide: Guide
|
hsguide: Guide
|
||||||
hsAble: Able
|
hsAble: Able
|
||||||
hsMenuTree: Menu Tree
|
hsMenuTree: Menu Tree
|
||||||
|
hsOptimize: Debounce、Throttle、Copy Directives
|
||||||
hsWatermark: Water Mark
|
hsWatermark: Water Mark
|
||||||
hsPrint: Print
|
hsPrint: Print
|
||||||
hsDownload: Download
|
hsDownload: Download
|
||||||
|
@ -68,6 +68,7 @@ menus:
|
|||||||
hsguide: 引导页
|
hsguide: 引导页
|
||||||
hsAble: 功能
|
hsAble: 功能
|
||||||
hsMenuTree: 菜单树结构
|
hsMenuTree: 菜单树结构
|
||||||
|
hsOptimize: 防抖、截流、复制指令
|
||||||
hsWatermark: 水印
|
hsWatermark: 水印
|
||||||
hsPrint: 打印
|
hsPrint: 打印
|
||||||
hsDownload: 下载
|
hsDownload: 下载
|
||||||
|
@ -7,7 +7,9 @@ export const auth: Directive = {
|
|||||||
if (value) {
|
if (value) {
|
||||||
!hasAuth(value) && el.parentNode?.removeChild(el);
|
!hasAuth(value) && el.parentNode?.removeChild(el);
|
||||||
} else {
|
} else {
|
||||||
throw new Error("need auths! Like v-auth=\"['btn.add','btn.edit']\"");
|
throw new Error(
|
||||||
|
"[Directive: auth]: need auths! Like v-auth=\"['btn.add','btn.edit']\""
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
33
src/directives/copy/index.ts
Normal file
33
src/directives/copy/index.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { message } from "@/utils/message";
|
||||||
|
import { useEventListener } from "@vueuse/core";
|
||||||
|
import { copyTextToClipboard } from "@pureadmin/utils";
|
||||||
|
import { Directive, type DirectiveBinding } from "vue";
|
||||||
|
|
||||||
|
interface CopyEl extends HTMLElement {
|
||||||
|
copyValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 文本复制指令(默认双击复制) */
|
||||||
|
export const copy: Directive = {
|
||||||
|
mounted(el: CopyEl, binding: DirectiveBinding) {
|
||||||
|
const { value } = binding;
|
||||||
|
if (value) {
|
||||||
|
el.copyValue = value;
|
||||||
|
const arg = binding.arg ?? "dblclick";
|
||||||
|
// Register using addEventListener on mounted, and removeEventListener automatically on unmounted
|
||||||
|
useEventListener(el, arg, () => {
|
||||||
|
const success = copyTextToClipboard(el.copyValue);
|
||||||
|
success
|
||||||
|
? message("复制成功", { type: "success" })
|
||||||
|
: message("复制失败", { type: "error" });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
'[Directive: copy]: need value! Like v-copy="modelValue"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updated(el: CopyEl, binding: DirectiveBinding) {
|
||||||
|
el.copyValue = binding.value;
|
||||||
|
}
|
||||||
|
};
|
@ -1 +1,3 @@
|
|||||||
export * from "./auth";
|
export * from "./auth";
|
||||||
|
export * from "./copy";
|
||||||
|
export * from "./optimize";
|
||||||
|
55
src/directives/optimize/index.ts
Normal file
55
src/directives/optimize/index.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
isFunction,
|
||||||
|
isObject,
|
||||||
|
isArray,
|
||||||
|
debounce,
|
||||||
|
throttle
|
||||||
|
} from "@pureadmin/utils";
|
||||||
|
import { useEventListener } from "@vueuse/core";
|
||||||
|
import { Directive, type DirectiveBinding } from "vue";
|
||||||
|
|
||||||
|
/** 防抖(v-optimize或v-optimize:debounce)、节流(v-optimize:throttle)指令 */
|
||||||
|
export const optimize: Directive = {
|
||||||
|
mounted(el: HTMLElement, binding: DirectiveBinding) {
|
||||||
|
const { value } = binding;
|
||||||
|
const optimizeType = binding.arg ?? "debounce";
|
||||||
|
const type = ["debounce", "throttle"].find(t => t === optimizeType);
|
||||||
|
if (type) {
|
||||||
|
if (value && value.event && isFunction(value.fn)) {
|
||||||
|
let params = value?.params;
|
||||||
|
if (params) {
|
||||||
|
if (isArray(params) || isObject(params)) {
|
||||||
|
params = isObject(params) ? Array.of(params) : params;
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"[Directive: optimize]: `params` must be an array or object"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Register using addEventListener on mounted, and removeEventListener automatically on unmounted
|
||||||
|
useEventListener(
|
||||||
|
el,
|
||||||
|
value.event,
|
||||||
|
type === "debounce"
|
||||||
|
? debounce(
|
||||||
|
params ? () => value.fn(...params) : value.fn,
|
||||||
|
value?.timeout ?? 200,
|
||||||
|
value?.immediate ?? false
|
||||||
|
)
|
||||||
|
: throttle(
|
||||||
|
params ? () => value.fn(...params) : value.fn,
|
||||||
|
value?.timeout ?? 1000
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"[Directive: optimize]: `event` and `fn` are required, and `fn` must be a function"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"[Directive: optimize]: only `debounce` and `throttle` are supported"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -10,6 +10,15 @@ export default {
|
|||||||
rank: able
|
rank: able
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: "/able/directives",
|
||||||
|
name: "Directives",
|
||||||
|
component: () => import("@/views/able/directives.vue"),
|
||||||
|
meta: {
|
||||||
|
title: $t("menus.hsOptimize"),
|
||||||
|
extraIcon: "IF-pure-iconfont-new svg"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/able/watermark",
|
path: "/able/watermark",
|
||||||
name: "WaterMark",
|
name: "WaterMark",
|
||||||
|
117
src/views/able/directives.vue
Normal file
117
src/views/able/directives.vue
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { message } from "@/utils/message";
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "Directives"
|
||||||
|
});
|
||||||
|
|
||||||
|
const search = ref("");
|
||||||
|
const searchTwo = ref("");
|
||||||
|
const searchThree = ref("");
|
||||||
|
const searchFour = ref("");
|
||||||
|
const searchFive = ref("");
|
||||||
|
const searchSix = ref("copy");
|
||||||
|
const text = ref("可复制的文本");
|
||||||
|
|
||||||
|
function onInput() {
|
||||||
|
message(search.value);
|
||||||
|
}
|
||||||
|
function onInputTwo() {
|
||||||
|
message(searchTwo.value);
|
||||||
|
}
|
||||||
|
function onInputThree({ name, sex }) {
|
||||||
|
message(`${name}${sex}${searchThree.value}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onInputFour() {
|
||||||
|
message(searchFour.value);
|
||||||
|
}
|
||||||
|
function onInputFive({ name, sex }) {
|
||||||
|
message(`${name}${sex}${searchFive.value}`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-card shadow="never">
|
||||||
|
<template #header>
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="font-medium">自定义防抖、截流、文本复制指令</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div class="mb-2">
|
||||||
|
防抖指令(连续输入,只会执行第一次点击事件,立即执行)
|
||||||
|
<el-input
|
||||||
|
v-optimize="{
|
||||||
|
event: 'input',
|
||||||
|
fn: onInput,
|
||||||
|
immediate: true,
|
||||||
|
timeout: 1000
|
||||||
|
}"
|
||||||
|
v-model="search"
|
||||||
|
class="!w-[200px]"
|
||||||
|
clearable
|
||||||
|
@clear="onInput"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
防抖指令(连续输入,只会执行最后一次事件,延后执行)
|
||||||
|
<el-input
|
||||||
|
v-optimize="{ event: 'input', fn: onInputTwo, timeout: 400 }"
|
||||||
|
v-model="searchTwo"
|
||||||
|
class="!w-[200px]"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
防抖指令(连续输入,只会执行最后一次事件,延后执行,传参用法)
|
||||||
|
<el-input
|
||||||
|
v-optimize="{
|
||||||
|
event: 'input',
|
||||||
|
fn: onInputThree,
|
||||||
|
timeout: 400,
|
||||||
|
params: { name: '小明', sex: '男' }
|
||||||
|
}"
|
||||||
|
v-model="searchThree"
|
||||||
|
class="!w-[200px]"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider />
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
节流指令(连续输入,每一秒只会执行一次事件)
|
||||||
|
<el-input
|
||||||
|
v-optimize:throttle="{ event: 'input', fn: onInputFour, timeout: 1000 }"
|
||||||
|
v-model="searchFour"
|
||||||
|
class="!w-[200px]"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
节流指令(连续输入,每一秒只会执行一次事件,传参用法)
|
||||||
|
<el-input
|
||||||
|
v-optimize:throttle="{
|
||||||
|
event: 'input',
|
||||||
|
fn: onInputFive,
|
||||||
|
params: { name: '小明', sex: '男' }
|
||||||
|
}"
|
||||||
|
v-model="searchFive"
|
||||||
|
class="!w-[200px]"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider />
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
文本复制指令(双击输入框内容即可复制)
|
||||||
|
<el-input v-copy="searchSix" v-model="searchSix" class="!w-[200px]" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
文本复制指令(自定义触发事件,单击复制)
|
||||||
|
<span v-copy:click="text" class="text-sky-500">{{ text }}</span>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
Loading…
x
Reference in New Issue
Block a user