Vue 3 显著增强了自定义指令的功能,使其封装更加灵活和易用。本文将分为基础和进阶两部分,介绍如何实现常用的自定义指令,并提供最佳的项目组织方式。
前言
- 本文以复制文本的自定义指令详细介绍自定义指令的基础知识
- 多个自定义指令如何进行代码及目录的组织
- 如何更好的进行方法抽离使公共方法和自定义指令进行解耦
- 自定义指令的高阶用法
1. 指令生命周期
Vue 3 自定义指令的生命周期如下:
created
:指令绑定到元素上时调用,且只调用一次。beforeMount
:在元素插入 DOM 之前调用。mounted
:元素插入 DOM 后调用。beforeUpdate
:更新包含绑定值的元素时调用,发生在更新前。updated
:更新包含绑定值的元素后调用。beforeUnmount
:在绑定元素从 DOM 中移除前调用。unmounted
:绑定元素从 DOM 中移除后调用。
通过这些生命周期,可以实现复杂的逻辑,例如初始化资源、监听事件或清理操作。
2. 基础部分:v-copy
指令
目标:实现一个简单的复制文本功能。
实现代码
将复制文本的逻辑单独抽离为工具函数:
javascript
// src/utils/copyToClipboard.js
export function copyToClipboard(text) {
const input = document.createElement('textarea');
input.value = text;
document.body.appendChild(input);
input.select();
try {
document.execCommand('copy');
document.body.removeChild(input);
return true;
} catch (err) {
document.body.removeChild(input);
throw new Error('复制失败');
}
}
封装 v-copy
指令:
javascript
// src/directives/copy.js
import { copyToClipboard } from '../utils/copyToClipboard';
import { isFunction } from '../utils/isType';
export default {
mounted(el, binding) {
const handleClick = () => {
try {
copyToClipboard(binding.value);
console.log('复制成功!');
} catch (err) {
console.error('复制失败:', err);
}
};
el.__handleClick__= handleClick;
el.removeEventListener('click', el.__handleClick__);
el.addEventListener('click', handleClick);
},
unmounted(el) {
el.removeEventListener('click', el.__handleClick__);
delete el.__handleClick__;
},
};
使用方式
在 Vue 项目中全局注册指令:
javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import copyDirective from './directives/copy';
const app = createApp(App);
app.directive('copy', copyDirective);
app.mount('#app');
在组件中使用:
xml
<template>
<button v-copy="'这是复制的文本'">点击复制</button>
</template>
3. 进阶部分:完善的 v-copy
指令
目标:增强功能,支持成功和失败的事件回调。
实现代码
javascript
// src/directives/copy.js
import { copyToClipboard } from '../utils/copyToClipboard';
import { isFunction } from '../utils/isType';
export default {
mounted(el, binding) {
const handleClick = () => {
const { success, error } = binding.arg || {};
try {
copyToClipboard(binding.value);
if (isFunction(success)) {
success();
}
} catch (err) {
if (isFunction(error)) {
error(err);
}
}
};
el.__handleClick__ = handleClick;
el.removeEventListener('click', el.__handleClick__);
el.addEventListener('click', handleClick);
},
unmounted(el) {
el.removeEventListener('click', el.__handleClick__);
delete el.__handleClick__;
},
};
使用方式
xml
<template>
<button
v-copy:success="onCopySuccess"
v-copy:error="onCopyError"
v-copy="'高级复制文本'"
>
高级复制按钮
</button>
</template>
<script>
export default {
methods: {
onCopySuccess() {
alert('复制成功!');
},
onCopyError(err) {
alert('复制失败:' + err.message);
},
},
};
</script>
4. 指令参数说明
binding.value
:指令绑定的值,在这里是需要复制的文本。binding.arg
:可选参数,例如用于传递回调函数(如success
和error
)。binding.modifiers
:修饰符对象,可用于定义指令的额外行为(如条件触发等)
5. 多指令项目的目录结构
当项目中包含多个自定义指令时,建议按照以下方式组织:
bash
src/
├── directives/
│ ├── index.js # 统一导出所有指令
│ ├── copy.js # 复制指令
│ ├── focus.js # 聚焦指令
│ └── lazy-load.js # 图片懒加载指令
├── utils/
│ ├── copyToClipboard.js # 工具函数
│ └── isType.js # 类型判断工具
统一导出指令
javascript
// src/directives/index.js
import copy from './copy';
import focus from './focus';
import lazyLoad from './lazy-load';
export default {
copy,
focus,
lazyLoad,
};
全局注册指令
javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import directives from './directives';
const app = createApp(App);
Object.keys(directives).forEach((key) => {
app.directive(key, directives[key]);
});
app.mount('#app');
通过这样的目录结构,指令的维护和扩展将更加方便有序。如果需要新增指令,只需在 directives
目录中添加对应的文件并更新 index.js
即可。
希望本文能够帮助您更好地掌握 Vue 3 的自定义指令开发!
6.团队介绍
「三翼鸟数字化技术平台-定制平台开发」主要负责设计工具的研发,包括营销设计工具、家电VR设计和展示、水电暖通前置设计能力,研发并沉淀素材库,构建家居家装素材库,集成户型库、全品类产品库、设计方案库、生产工艺模型,打造基于户型和风格的AI设计能力,快速生成算量和报价;同时研发了门店设计师中心和项目中心,包括设计师管理能力和项目经理管理能力。实现了场景全生命周期管理,同时为水,空气,厨房等产业提供商机管理工具,从而实现了以场景贯穿的B端C端全流程系统。