Vue.js 自定义指令:从零开始创建自己的指令

vue使用directive

前言

关于使用自定义指令在官网中是这样描述的

vue2:对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

vue3:自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。

在 Vue.js 中使用自定义指令(directive)可以带来许多好处,包括但不限于这些:

  • 代码复用:自定义指令可以封装一些常用的 DOM 操作,使得这些操作可以在多个组件中复用,减少代码冗余。
  • 简化模板:通过自定义指令,可以将一些复杂的 DOM 操作从模板中移除,使模板更加简洁和易读。
  • 增强功能:自定义指令可以提供一些 Vue 框架本身不直接支持的功能,比如自动聚焦、拖拽、动画等。
  • 更好的封装性:自定义指令可以将 DOM 操作的逻辑封装在指令内部,使得组件的代码更加清晰和模块化。
  • 更细粒度的控制:自定义指令可以绑定到特定的 DOM 元素或属性,提供更细粒度的控制,比如只对某个元素应用某些效果。
  • 生命周期钩子:自定义指令提供了生命周期钩子函数,可以在不同的阶段执行特定的逻辑。

vue2使用

在vue2使用使用directive根据官网介绍可以这样使用

javascript 复制代码
// 注册一个全局自定义指令 `v-focus`
import Vue from 'vue'
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时......
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

然后在页面中绑定

javascript 复制代码
<input v-focus>

这样就能 聚焦元素 的效果

当然在项目中可以更加优化

这里单独创建一个文件夹来存放自定义指令的js文件并使用index导出引入的文件, 这里拿两个实例来举例子 ,一个是复制文本的copy.js文件,一个控制权限的role.js文件。

main.js 文件这样集中引入指令文件

javascript 复制代码
import Vue from 'vue'
import App from './App.vue'
import directives from './directives';

Vue.config.productionTip = false

Object.keys(directives).forEach(name => {
  Vue.directive(name, directives[name]);
});

new Vue({
  render: h => h(App),
}).$mount('#app')

index.js 文件导出引入的指令

javascript 复制代码
import copy from './copy';
import role from './role';

export default {
	copy,
	role
};

copy.js文件

javascript 复制代码
import { Message } from 'element-ui';
let timer = null;
const copy = {
	bind(el, binding) {
		if (binding.value) {
			el.addEventListener('click', () => copyClick(el, binding));
		}
	},
};
const copyClick = (el, binding) => { 
	if (timer) clearTimeout(timer);
	timer = setTimeout(async () => { 
		await navigator.clipboard.writeText(binding.value);
		Message.success('复制成功!');
		timer = null;
	}, 200);
};
export default copy;

role.js文件

javascript 复制代码
const role = {
	bind (el, binding) { 
	    //只有包含了2的dom元素才显示
		if (!binding.value.includes(2)) {
			el.style.display = 'none';
		}
	},
};

export default role;

最后在文件中使用

javascript 复制代码
<template>
    <div class="hello">
        <el-button type="primary" round v-copy="text">点击我复制</el-button>

        <li v-role="[1]">这是一号dom</li>
        <li v-role="[1,2]">这是二号dom</li>
        <li v-role="[1,2,3]">这是三号dom</li>
    </div>
</template>

<script>
export default {
    name: 'HelloWorld',
    data () {
        return {
            text: 'hello world'
        }
    }
}
</script>

最后看实际效果

这就是基础的使用,

关于生命周期钩子函数

官网提供了像bindinsertedupdatecomponentUpdatedunbind等,可以在不同的阶段执行特定的逻辑。

更多的参考 vue2指令官网

vue3使用

在vue3中使用指令与vue2写法有点不同

官网是这样使用的

javascript 复制代码
const app = createApp({})

// 使 v-focus 在所有组件中都可用
app.directive('focus', {
  /* ... */
})

// 使用的组件
<template>
  <input v-focus />
</template>

这里的举例跟vue2的一样,不过项目是用vite+ts搭建的

单独创建一个文件夹来存放自定义指令的js文件并使用index导出引入的文件, 这里拿两个实例来举例子 ,复制文本的copy.ts文件和控制权限的role.ts文件。

main.ts 文件这样集中引入指令文件

javascript 复制代码
import { createApp } from 'vue' 
import App from './App.vue' 
import directives from './directives';

const app = createApp(App)

for (const [name, directive] of Object.entries(directives)) {
	app.directive(name, directive);
}   

app.mount('#app')

在index.ts 文件中导出

javascript 复制代码
import copy from './copy';
import role from './role';

export default {
	copy,
	role
};

copy.ts文件

javascript 复制代码
import { DirectiveBinding } from 'vue';
import { ElMessage } from 'element-plus';
let timer: any = null;
const copy = {
	mounted(el: HTMLElement, binding: DirectiveBinding) {
		if (binding.value) {
			el.addEventListener('click', () => copyClick(el, binding));
		}
	},
};
const copyClick = (el: HTMLElement, binding: DirectiveBinding) => { 
	if (timer) clearTimeout(timer);
	timer = setTimeout(async () => {
		// 复制文本
		await navigator.clipboard.writeText(binding.value);
		ElMessage.success('复制成功!');
		timer = null;
	}, 200);
};
export default copy;

role.ts文件

javascript 复制代码
import { DirectiveBinding } from 'vue';
const role = {
	mounted(el: HTMLElement, binding: DirectiveBinding) {
	    //包含了 2 的元素才显示
		if (!binding.value.includes(2)) {
			el.remove();
		}
	},
};
export default role;

使用的vue件

javascript 复制代码
<script setup lang="ts">
import { ref } from "vue";
const text = ref("这是赋值的值12345");
</script>

<template>
    <el-button type="primary" round v-copy="text">点击我复制</el-button>

    <li v-role="[1]">这是一号dom</li>
    <li v-role="[1,2]">这是二号dom</li>
    <li v-role="[1,2,3]">这是三号dom</li>
</template>

最后看效果

最后关于生命周期钩子函数,官网给出了这些

更多的扩展使用可以参考官网
vue3指令官网

相关推荐
颜酱2 小时前
图结构完全解析:从基础概念到遍历实现
javascript·后端·算法
失忆爆表症3 小时前
05_UI 组件库集成指南:Shadcn/ui + Tailwind CSS v4
前端·css·ui
小迷糊的学习记录3 小时前
Vuex 与 pinia
前端·javascript·vue.js
发现一只大呆瓜3 小时前
前端性能优化:图片懒加载的三种手写方案
前端·javascript·面试
不爱吃糖的程序媛3 小时前
Flutter 与 OpenHarmony 通信:Flutter Channel 使用指南
前端·javascript·flutter
利刃大大3 小时前
【Vue】Element-Plus快速入门 && Form && Card && Table && Tree && Dialog && Menu
前端·javascript·vue.js·element-plus
NEXT063 小时前
AI 应用工程化实战:使用 LangChain.js 编排 DeepSeek 复杂工作流
前端·javascript·langchain
念风零壹4 小时前
AI 时代的前端技术:从系统编程到 JavaScript/TypeScript
前端·ai
光影少年4 小时前
react的hooks防抖和节流是怎样做的
前端·javascript·react.js
小毛驴8504 小时前
Vue 路由示例
前端·javascript·vue.js