自定义指令
在Vue.js中,自定义指令提供了一种非常灵活的方式来扩展Vue的功能。以下是对Vue中自定义指令的详细解释:
一、自定义指令的基本概念
自定义指令允许开发者直接对DOM元素进行低层次操作,而无需编写大量的模板或者JavaScript代码。它们可以响应Vue的响应式系统,从而在数据变化时触发相应的DOM更新。
二、自定义指令的注册
- 全局注册:
使用Vue.directive(name, definition)
方法可以在全局范围内注册一个自定义指令。例如:
Vue.directive('my-directive', {
// 指令的定义
bind: function (el, binding, vnode, oldVnode) {
// 只调用一次,指令第一次绑定到元素时调用
// 在这里可以进行一次性的初始化设置
},
// 其他钩子函数...
});
- 局部注册:
在组件中,可以使用directives
选项来局部注册自定义指令。例如:
export default {
directives: {
'my-directive': {
// 指令的定义
bind: function (el, binding, vnode) {
// ...
},
// 其他钩子函数...
}
},
// 其他组件选项...
};
或者在setup
函数中使用directives
选项:
<script setup>
const myDirective = {
// 指令的定义
mounted: (el) => {
// ...
},
// 其他钩子函数...
};
</script>
<template>
<div v-my-directive></div>
</template>
三、自定义指令的钩子函数
自定义指令可以包含多个钩子函数,这些钩子函数在指令的不同生命周期阶段被调用:
- bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
- inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
- update:所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。
- componentUpdated:指令所在组件的VNode及其子VNode全部更新后调用。
- unbind:只调用一次,指令与元素解绑时调用。
四、自定义指令的参数和修饰符
- 参数:指令的参数可以是动态的,通过
v-mydirective:[argument]="value"
的形式传递。在指令的钩子函数中,可以通过binding.arg
访问到参数的值。 - 修饰符:修饰符是以
.
开头的特殊后缀,用于对指令的行为进行微调。在指令的钩子函数中,可以通过binding.modifiers
访问到修饰符的对象。
五、自定义指令的示例
以下是一个简单的自定义指令示例,用于在元素上添加点击时的动画效果:
Vue.directive('click-animate', {
bind(el, binding) {
// 定义点击时的动画效果
el.animateClick = () => {
el.classList.add('click');
setTimeout(() => {
el.classList.remove('click');
}, 100);
};
},
handleEvent(event) {
if (event.type === 'click') {
el.animateClick();
}
}
});
在模板中使用:
<button v-click-animate>Click me!</button>
六、自定义指令的注意事项
- 在使用自定义指令时,请确保指令的名称不与Vue的内置指令冲突。
- 在指令的钩子函数中,请避免直接修改
binding
对象的属性,因为它是只读的。 - 如果需要在多个组件中重复使用自定义指令,建议将其注册为全局指令。
综上所述,Vue中的自定义指令提供了一种强大的方式来扩展Vue的功能,允许开发者直接对DOM元素进行低层次操作,并响应数据的变化。通过合理地使用自定义指令,可以实现各种复杂的DOM操作和逻辑控制。
若依框架中自定义指令分析
1.登录系统
根据用户后端返回用户信息,包括permisssions(Array)、roles和users 信息
2.封装v-hasPermi指令(src/directive/permission/hasPermi.js)
用于判断当前用户是否有此权限。没有此权限(如:普通用户没有删除信息的权限)对应按钮就将移除【通过指令钩子函数的el参数修改DOM】
import store from '@/store'
export default {
//可访问到DOM
inserted(el, binding, vnode) {
const { value } = binding
const all_permission = "*:*:*";//所有权限
const permissions = store.getters && store.getters.permissions//vuex中存的当前用户右的权限
//绑定时为v-hasPermi="[]",值为数组类型
if (value && value instanceof Array && value.length > 0) {
const permissionFlag = value//当前按钮所需权限
//当前用户是否存在此权限
const hasPermissions = permissions.some(permission => {
return all_permission === permission || permissionFlag.includes(permission)
})
if (!hasPermissions) {
//没有对应权限就移除对应按钮!!!
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`请设置操作权限标签值`)
}
}
}
3.导出所有自定义指令至插件index.js(src/directive/index.js)
将项目封装的所有指令以插件的型式导出去
import hasRole from './permission/hasRole'
import hasPermi from './permission/hasPermi'
import dialogDrag from './dialog/drag'
import dialogDragWidth from './dialog/dragWidth'
import dialogDragHeight from './dialog/dragHeight'
import clipboard from './module/clipboard'
const install = function(Vue) {
Vue.directive('hasRole', hasRole)
Vue.directive('hasPermi', hasPermi)
Vue.directive('clipboard', clipboard)
Vue.directive('dialogDrag', dialogDrag)
Vue.directive('dialogDragWidth', dialogDragWidth)
Vue.directive('dialogDragHeight', dialogDragHeight)
}
if (window.Vue) {
window['hasRole'] = hasRole
window['hasPermi'] = hasPermi
Vue.use(install); // eslint-disable-line
}
export default install
4.使用指令
使用 v-directiveName="value"
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:dept:add']"
>新增</el-button>