Vue3+ts自定义指令

发布于:2025-08-03 ⋅ 阅读:(14) ⋅ 点赞:(0)

1. 在 directives/index.ts 中整合自定义指令:

在 src/directives/index.ts 文件中定义多个自定义指令。

// 防抖指令
interface DebounceBinding {
    (): void;
    time?: number;
    logPrefix?: string;
}

export const debounce: Directive = {
    mounted(el: HTMLElement, binding: { arg: string; value: DebounceBinding }) {
        let timer: NodeJS.Timeout | null = null;
        el.addEventListener(binding.arg, () => {
            if (timer) {
                clearTimeout(timer);
            }
            const delay = binding.value.time || 300;
            const logPrefix = binding.value.logPrefix || 'Debounce';
            timer = setTimeout(() => {
                console.log(`${logPrefix}: 防抖后的函数执行`);
                binding.value();
            }, delay);
        });
    },
    unmounted(el: HTMLElement) {
        if (timer) {
            clearTimeout(timer);
        }
    }
};

// 聚焦指令
export const focus: Directive = {
    inserted(el: HTMLElement) {
        el.focus();
    }
};

// 图片懒加载指令
export const lazyload: Directive = {
    mounted(el: HTMLImageElement, binding: { value: string }) {
        const img = new Image();
        const loadingClass = 'image-loading';
        const errorClass = 'image-error';

        el.classList.add(loadingClass);

        const observer = new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    img.src = binding.value;
                    img.onload = () => {
                        el.src = binding.value;
                        el.classList.remove(loadingClass);
                        observer.unobserve(el);
                    };
                    img.onerror = () => {
                        el.classList.remove(loadingClass);
                        el.classList.add(errorClass);
                        observer.unobserve(el);
                    };
                }
            });
        });

        observer.observe(el);
    }
};

2. 在 main.ts 中全局注册自定义指令:

import { createApp } from 'vue';
import App from './App.vue';
import { debounce, focus, lazyload } from './directives';

const app = createApp(App);

app.directive('debounce', debounce);
app.directive('focus', focus);
app.directive('lazyload', lazyload);

app.mount('#app');

3. 在组件中使用自定义指令:

在 XXX.vue 中使用这几个自定义指令。

<template>
    <div>
        <input v-focus type="text" placeholder="自动聚焦">
        <input type="text" v-debounce:input="inputDebounce" :time="500" :logPrefix="自定义前缀">
        < img v-lazyload="imageUrl" alt="示例图片">
    </div>
</template>

<script setup lang="ts">
const inputDebounce = () => {
    console.log('实际执行的函数');
};

const imageUrl = 'your-image-url.jpg';
</script>

在上述代码中,我们将 debounce 和 focus 两个自定义指令都定义在 directives/index.ts 文件中,然后在 main.ts 中进行全局注册,并在 App.vue 组件中使用它们。这样的结构使自定义指令的管理更加集中和清晰。


网站公告

今日签到

点亮在社区的每一天
去签到