feat: 自定义指令

This commit is contained in:
wang_fan_w 2024-07-13 18:47:45 +08:00
parent 6d901938d5
commit f7c9bb2188
7 changed files with 131 additions and 42 deletions

View File

@ -1,19 +1,14 @@
import { Directive } from "vue";
const myDirective: Directive = {
beforeMount(el, binding) {
el.style.color = binding.value;
}
};
import antiShake from "@/directives/modules/anti-shake";
import throttle from "@/directives/modules/throttle";
// 定义安装函数
// install 函数是一个对象中的方法,其作用是将一系列指令对象安装到 Vue 应用实例中它自带两个参数app 和 options
// app就是vue实例options则是安装函数的参数(可选)
// install 方法的定义就插件对象install 方法会在引入插件时自动被 vue 调用,并传参 vue 实例和 options
const directives = {
install(app: any, options?: any) {
install(app: any) {
// 将一系列自定义指令对象安装到 Vue 应用实例中
app.directive("my-directive", myDirective);
app.directive("antiShake", antiShake);
app.directive("throttle", throttle);
}
};

View File

@ -0,0 +1,50 @@
import { Directive } from "vue";
const antiShake: Directive = {
mounted(el, binding) {
// 判断是否是函数,防抖指令必须绑定函数
if (typeof binding.value != "function") {
return console.warn("Anti-shake instructions must be bound to a function");
}
let timeout: any = null;
// 给el添加自定义事件-防抖函数
el.__onClick__ = () => {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
// 由于绑定的是函数,这里直接调用绑定之即可(也就是调用绑定的函数)
binding.value();
}, 500);
};
// 监听点击事件,点击后调用绑定的自定义事件
el.addEventListener("click", el.__onClick__);
},
beforeUnmount(el) {
el.removeEventListener("click", el.__onClick__);
}
};
export default antiShake;
// 每个生命周期都有两个参数el、binding
// 其中el为绑定的dom元素binding为指令的传入值
// app.directive("focus", {
// 在绑定元素的 attribute 前
// 或事件监听器应用前调用
// created(el, binding, vnode) {
// // 下面会介绍各个参数的细节
// },
// // 在元素被插入到 DOM 前调用
// beforeMount(el, binding, vnode) {},
// // 在绑定元素的父组件
// // 及他自己的所有子节点都挂载完成后调用
// mounted(el, binding, vnode) {},
// // 绑定元素的父组件更新前调用
// beforeUpdate(el, binding, vnode, prevVnode) {},
// // 在绑定元素的父组件
// // 及他自己的所有子节点都更新后调用
// updated(el, binding, vnode, prevVnode) {},
// // 绑定元素的父组件卸载前调用
// beforeUnmount(el, binding, vnode) {},
// // 绑定元素的父组件卸载后调用
// unmounted(el, binding, vnode) {}
// });

View File

@ -0,0 +1,31 @@
import { Directive } from "vue";
const throttle: Directive = {
mounted(el, binding) {
if (typeof binding.value != "function") {
return console.warn("The throttling instruction must be bound to a function");
}
let countDown = 0;
let timer: any = null;
el.__onClick__ = () => {
if (timer) return;
if (countDown == 0) {
binding.value();
countDown = 1;
}
timer = setInterval(() => {
countDown--;
if (countDown <= 0) {
clearInterval(timer);
timer = null;
}
}, 1000);
};
el.addEventListener("click", el.__onClick__);
},
beforeUnmount(el) {
el.removeEventListener("click", el.__onClick__);
}
};
export default throttle;

View File

@ -23,10 +23,12 @@ import "@/assets/fonts/fonts.scss";
import directives from "@/directives/index";
initVChartArcoTheme();
const app = createApp(App);
// app.use(plugin, options)
// 其中 plugin 表示要传递的插件对象, options 参数是可选的,表示选项配置
// https://cn.vuejs.org/api/application.html#app-use
app.use(ArcoVue, {
componentPrefix: "arco"

View File

@ -1,23 +1,27 @@
<template>
<FillPage>
<div class="scope-page">
<div class="my-page" v-my-directive="'red'">防抖</div>
<div class="dc-page">
<div class="title">自定义防抖指令连续点击按钮0.5s后执行一次</div>
<div class="button-box"><a-button type="primary" style="width: 100px" v-antiShake="onClick">防抖</a-button></div>
</div>
</FillPage>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { Message } from "@arco-design/web-vue";
const onClick = () => {
Message.info("0.5s后执行了");
};
</script>
<style lang="scss" scoped>
.scope-page {
box-sizing: border-box;
height: 100%;
padding: $padding;
.my-page {
height: 100%;
padding: $padding;
box-sizing: border-box;
background: $color-bg-1;
}
.title {
text-align: center;
color: $color-text-1;
font-size: $font-size-title-1;
}
.button-box {
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@ -1,23 +1,31 @@
<template>
<FillPage>
<div class="scope-page">
<div class="my-page">节流</div>
<div class="dc-page">
<div class="my-page">
<div class="title">自定义节流指令连续点击按钮每间隔1s执行一次</div>
<div class="button-box">
<a-button type="primary" style="width: 100px" v-throttle="onClick">1s节流</a-button>
</div>
</div>
</div>
</FillPage>
</template>
<script setup lang="ts"></script>
<script setup lang="ts">
import { Message } from "@arco-design/web-vue";
const onClick = () => {
Message.info("节流执行了");
};
</script>
<style lang="scss" scoped>
.scope-page {
box-sizing: border-box;
height: 100%;
padding: $padding;
.my-page {
height: 100%;
padding: $padding;
box-sizing: border-box;
background: $color-bg-1;
}
.title {
text-align: center;
color: $color-text-1;
font-size: $font-size-title-1;
}
.button-box {
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
</style>

View File

@ -12,7 +12,6 @@
</div>
</div>
</template>
<script setup lang="ts">
import LoginBanner from "@/views/login/components/login-banner.vue";
import LoginForm from "@/views/login/components/login-form.vue";