feat: 自定义指令
This commit is contained in:
parent
6d901938d5
commit
f7c9bb2188
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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) {}
|
||||
// });
|
||||
31
src/directives/modules/throttle.ts
Normal file
31
src/directives/modules/throttle.ts
Normal 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;
|
||||
@ -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"
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user