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指令官网

相关推荐
理想不理想v2 分钟前
【经典】webpack和vite的区别?
java·前端·javascript·vue.js·面试
羊子雄起13 分钟前
CKEditor前端样式和编辑器的样式不一致的问题
前端·编辑器
聊无生28 分钟前
JavaSrcipt 函数高级
开发语言·前端·javascript
xiyusec1 小时前
HTML基础
前端·html
好开心331 小时前
javaScript交互案例2
开发语言·前端·javascript·html·ecmascript·交互
xChive1 小时前
优化表单交互:在 el-select 组件中嵌入表格显示选项
前端·vue.js·交互·element-plus
tian-ming1 小时前
(十八)JavaWeb后端开发案例——会话/yml/过滤器/拦截器
java·开发语言·前端
duansamve1 小时前
WebGIS地图框架有哪些?
javascript·gis·openlayers·cesium·mapbox·leaflet·webgis
_jacobfu1 小时前
mac2024 安装node和vue
前端·javascript·vue.js
Ztiddler1 小时前
【npm设置代理-解决npm网络连接error network失败问题】
前端·后端·npm·node.js·vue