自定义指令
在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 {//可访问到DOMinserted(el, binding, vnode) {const { value } = bindingconst 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'] = hasRolewindow['hasPermi'] = hasPermiVue.use(install); // eslint-disable-line
}export default install
4.使用指令
使用 v-directiveName="value"
<el-buttontype="primary"plainicon="el-icon-plus"size="mini"@click="handleAdd"v-hasPermi="['system:dept:add']">新增</el-button>