当前位置: 首页 > article >正文

Vue自定义指令详解——以若依框架中封装指令为例分析

自定义指令

在Vue.js中,自定义指令提供了一种非常灵活的方式来扩展Vue的功能。以下是对Vue中自定义指令的详细解释:

一、自定义指令的基本概念

自定义指令允许开发者直接对DOM元素进行低层次操作,而无需编写大量的模板或者JavaScript代码。它们可以响应Vue的响应式系统,从而在数据变化时触发相应的DOM更新。

二、自定义指令的注册

  1. 全局注册

使用Vue.directive(name, definition)方法可以在全局范围内注册一个自定义指令。例如:

Vue.directive('my-directive', {
// 指令的定义
bind: function (el, binding, vnode, oldVnode) {
// 只调用一次,指令第一次绑定到元素时调用
// 在这里可以进行一次性的初始化设置
},
// 其他钩子函数...
});
  1. 局部注册

在组件中,可以使用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>

三、自定义指令的钩子函数

自定义指令可以包含多个钩子函数,这些钩子函数在指令的不同生命周期阶段被调用:

  1. bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
  2. inserted:被绑定元素插入父节点时调用(仅保证父节点存在,但不一定已被插入文档中)。
  3. update:所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。
  4. componentUpdated:指令所在组件的VNode及其子VNode全部更新后调用。
  5. unbind:只调用一次,指令与元素解绑时调用。

四、自定义指令的参数和修饰符

  1. 参数:指令的参数可以是动态的,通过v-mydirective:[argument]="value"的形式传递。在指令的钩子函数中,可以通过binding.arg访问到参数的值。
  2. 修饰符:修饰符是以.开头的特殊后缀,用于对指令的行为进行微调。在指令的钩子函数中,可以通过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>

六、自定义指令的注意事项

  1. 在使用自定义指令时,请确保指令的名称不与Vue的内置指令冲突。
  2. 在指令的钩子函数中,请避免直接修改binding对象的属性,因为它是只读的。
  3. 如果需要在多个组件中重复使用自定义指令,建议将其注册为全局指令。

综上所述,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>


http://www.kler.cn/a/391737.html

相关文章:

  • 数据库SQL——连接表达式(JOIN)图解
  • 【前端】Vue中如何避免出现内存泄漏
  • AMD CPU下pytorch 多GPU运行卡死和死锁解决
  • request爬虫库的小坑
  • Java 网络编程(一)—— UDP数据报套接字编程
  • RoseTTAFold MSA_emb类解读
  • 从建立TRUST到实现FAIR:可持续海洋经济的数据管理
  • G-Star光引计划启动|投稿GitCode项目故事赢AirPods Pro,通过必得京东卡!
  • C++学习笔记----11、模块、头文件及各种主题(一)---- 模板概览与类模板(6)
  • 显示微服务间feign调用的日志
  • 系统架构(01架构的特点,本质...)
  • 技术栈2:Git分布式版本控制工具
  • pycharm快速更换虚拟环境
  • 文档数字化采集与智能处理:图像弯曲矫正技术概述
  • golang 泛型 middleware 设计模式: 一次只做一件事
  • (已解决)Java不是内部或者外部命令,也不是可运行的程序
  • 工位管理新纪元:Spring Boot企业系统
  • Chrome使用IE内核
  • SCUI Admin + Laravel 整合
  • 网络安全-蓝队基础
  • 科学计算服务器:如何计算算力?如何提升科学研究效率?
  • 音视频入门基础:MPEG2-TS专题(4)——使用工具分析MPEG2-TS传输流
  • Python、selenium 自动化 - 实现自动上传外部文件
  • Flutter 小技巧之 OverlayPortal 实现自限性和可共享的页面图层
  • 设计模式(四)装饰器模式
  • RHEL 网络配置(Linux网络服务器 09)