首页 > 其他分享 >vue自定义指令及常用自定义指令#记录

vue自定义指令及常用自定义指令#记录

时间:2024-03-25 18:01:53浏览次数:17  
标签:el Vue 自定义 vue binding focus 指令

一、什么是自定义指令

在vue官方文档中是这样描述的,自定义指令主要是为了重用涉及普通元素的底层DOM访问的逻辑。自定义指令主要分为全局自定义指令和局部自定义指令。

二、自定义指令相关参数

Vue 2.X钩子函数:

  • bind:自定义指令绑定到DOM后调用。只调用一次,指令第一次绑定到元素的调用。在这里可以进行一次性的初始化设置。注意:只是加入进了DOM,但是渲染没有完成。
  • inserted:自定义指令所在DOM,插入到父DOM后调用,渲染已经完成(父节点存在即可调用,不必存在于document中)。
  • update:元素更新,但子元素尚未更新,将调用此钩子(自定义指令所在组件更新时执行,但是不保证更新完成),和自定义指令所在组件有关。
  • componentUpdated:组件和子级更新后执行(自定义指令所在组件更新完成,且子组件也完成更新)。
  • unbind:解绑(销毁)(自定义指令所在DOM销毁时执行),只调用一次。

Vue 3.X钩子函数:

  • created:自定义指令所在组件,创建后调用。
  • beforeMount:相当于Vue 2.X中的bind,当元素被插入到DOM前调用。
  • mounted:相当于Vue 2.X中的inserted,当绑定元素的父组件被挂载后调用。
  • beforeUpdate:绑定元素的父组件更新前调用。
  • updated:相当于Vue 2.X中的componentUpdated,在绑定元素的父组件及他自己的所有子节点都更新后调用。
  • beforeUnmount:绑定元素的父组件卸载前调用。
  • unmounted:绑定元素的父组件卸载后调用。

指令的钩子会传递以下几种参数:

  • el:指令绑定到的元素。这可以直接操作DOM。
  • binding:一个对象,包含以下属性。
    • value:传递给指令的值。例如在v-my-directive="1"中,值是1。
    • oldValue:之前的值,仅在beforeUpdateupdated中可用。无论值是否更改,它都可用。
    • arg:传递给指令的参数(如果有的话)。例如在v-my-directive:add中,参数是"add"。
    • modifiers:一个包含修饰符的对象(如果有的话)。例如在v-my-directive:foo:bar中,修饰符对象是{ foo: true, bar: true }。
    • instance:使用该指令的组件实例。
    • dir:指令的定义对象。
  • vnode:代表绑定元素的底层VNode。虚拟DOM节点,一个真实DOM元素的蓝图,对应el。
  • prevNode:上一个虚拟节点。之前的渲染中代表指令所绑定元素的VNode。仅在beforUpdateupdated钩子中使用。

 三、注册自定义指令

 自定义指令要分全局自定义指令局部指令(以注册一个v-focus指令为例子)

 全局指令:通过应用实例注册一个全局自定义指令

  Vue.directive(指令名, { 自定义指令生命周期 })

// Vue 2.X
import Vue from 'vue'

Vue.directive('focus', {
    inserted: function(el) {
        el.focus()
    }
})

// Vue 3.X
const app = createApp({})

app.directive('focus', {
    mounted(el) {
        el.focus()
    }
})

局部指令:可在组件中配置directives选项来注册局部指令

directives(指令名, { 自定义指令生命周期 })

// Vue 2.X
directives: {
    focus: {
        inserted: function(el) {
            el.focus()
        }
    }
}

// Vue 3.X
directives: {
    focus: {
        mounted(el) {
            el.focus()
        }
    }
}

四、批量注册

1、创建专门放指令的文件夹directives,在文件夹中创建index.js文件。

2、在index.js文件中将所有指令引入后,写到一个对象中,并导出。

import debounce from './debounce'
import focus from './focus'
   
const directives = {
   debounce,
   focus
}
   
 export default {
   install(Vue) {
       Object.keys(directives).forEach(key => {
          Vue.directive(key, directives[key])
       })
    }
  }

3、 在main.js文件中引入

// Vue 2.X
import Vue from 'vue'
import Directive from './directives'
   
Vue.use(Directive)

// Vue 3.X
import { createApp } from 'vue'
import App from './App.vue'
import Directive from './directives'
   
const app = createApp(App)
   
app.use(Directive)
   
app.mount('#app')

五、常用指令

1、防抖指令 v-debounce

定义:n 秒后再执行该事件,若在 n 秒内被重复触发,则重新计时。

场景:项目开发中,经常会遇到按钮多次点击后,重复请求接口,造成数据混乱,例如表单数据提交。

vue2写法:
const debounce = {
    inserted: (el, binding) => {
        // 没有绑定函数抛出错误
        if (typeof binding.value !== 'function') {
            throw 'debounce callback not a function'
        }

        let timer
        el.addEventListener('click', () => {
            if (timer) clearTimeout(timer)

            timer = setTimeout(() => {
                binding.value()
            }, 1000)
        })
    }
}
export default debounce

vue3写法:
const debounce = {
  mounted: (el, binding) => {
    let timer
    el.addEventListener('click', () => {
      if (timer) {
        clearTimeout(timer)
      }
      timer = setTimeout(() => {
        binding.value()
      }, 1000)
    })
  },
}
export default debounce

//使用场景
<template>
    <button v-debounce="handleDebounce">防抖</button>
</template>

<script>
    export default {
        methods: {
            handleDebounce() {
                console.log('防抖,触发一次')
            }
        }
    }
</script>

2、节流指令 v-throttle

定义: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效。

场景:多数在监听页面元素滚动事件的时候会用到。因为滚动事件,是一个高频触发的事件。

const throttle = {
    bind: (el, binding) => {
        // 没有绑定函数抛出错误
        if (typeof binding.value !== 'function') {
            throw 'throttle callback not a function'
        }

        // 开关
        el._flag = true
        el._timer = null
        el._handler = () => {
            if (!el._flag) return

            // 函数执行后关闭开关
            el._flag && binding.value()
            el._flag = false

            if (el._timer) clearTimeout(el._timer)

            el._timer = setTimeout(_ => {
                el._flag = true
            }, 1000)
        }
        el.addEventListener('scroll', el._handler)
    },
    unbind: (el, binding) => {
        el.removeEventListener('scroll', el._handler)
    }
}

export default throttle

3、滚动到底部监听v-scroll-btm

Vue.directive('scroll-btm', {
  inserted(el, binding) {
    const { onScrollBtm, getContainer } = binding.value // onScrollBtm 触底回调,getContainer 获取滚动的容器,若无则自动选择挂载的dom
    const target = getContainer ? getContainer() : el
    if (!target.addEventListener) {
      console.warn('请确认传递的容器为Dom!')
      return
    }
    onScrollBtm && target.addEventListener('scroll', () => {
      if (target.scrollHeight - target.scrollTop - target.clientHeight < 1) {
        onScrollBtm() // 到底回调
      }
    })
  }
})


<template>
    <div id="tableScroll"> 
        <a-table v-scroll-btm="{getContainer: getEl ,onScrollBtm: handleToBtm}" :pagination="false"></a-table>    
    </div>
</template>

getEl () {
  return document.getElementById('tableScroll').getElementsByClassName('ant-table-body')[0]
},

//滑动至底部 触发事件
handleToBtm () {
  if (this.pageOpt.total > this.dataSource.length) {
     this.pageOpt.current++
     this.getDeviceList()
  }
},

4、按钮权限

Vue.directive('perm-btn', {
  inserted(el, binding) {
    if (!permissionJudge(binding.value) && el.parentNode) {
      el.parentNode.removeChild(el);
    }
    function permissionJudge(value: string) {
      // 此处store.getters.getMenuBtnList代表vuex中储存的按钮菜单数据
      let list = store.getters.perm_btn
      for (let item of list) {
        if (item === value) {
          return true
        }
      }
      return false
    }
  }
})

<Button type="primary" v-perm-btn="50"></Button>

标签:el,Vue,自定义,vue,binding,focus,指令
From: https://blog.csdn.net/junsens/article/details/136938865

相关文章

  • vue2和vue3的主要区别#记录
    一、 vue2和vue3的区别1、vue2和vue3双向数据绑定原理发生了改变vue2 的双向数据绑定是利用ES5的一个API Object.definePropert()对数据进行劫持结合发布订阅模式的方式来实现的。vue3 中使用了es6的 ProxyAPI对数据代理。相比于vue2.x,使用proxy的优势如下de......
  • 实现自定义队列
    publicclassMyQueue{privateint[]array;privateintfront;privateintrear;publicMyQueue(intcapacity){this.array=newint[capacity];}publicvoidenQueue(intelement){if((rear+1)%array.length==front)......
  • Vs Code中运行vue命令显示"系统禁止运行脚本"无法在终端使用
    右键点击vscode中的属性,在上面找到兼容性一栏,勾选里面以管理员身份运行在当前电脑中搜索WindowsPowerShell以管理员的身份运行 在里面输入 set-ExecutionPolicyRemoteSigned选择权限A ......
  • Vue学习笔记58--vuex
    vuex专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。Github地址:https://github.com/vuejs/vuex什么时候使用Vuex多个组件依赖于同一状态来自不同组件的行为需要......
  • vue中导出excel表格, Workbook 导出的表格的单元格格式设置为文本
    <template><button@click="exportExcel">导出Excel</button></template><script>importXLSXfrom'xlsx';exportdefault{methods:{exportExcel(){//创建Workbook和工作表constworkbook=......
  • 基于vue+element ui实现下拉表格选择组件
    一:前言本文属于转载;二:正文1:示例展示单选多选index.vue<template><el-selectref="select"v-model="defaultValue":title="isNeedTitle?getTitle():null":clearable="false":multiple="multiple"......
  • 自定义LocaleResolver 未生效
    问题原因自定义的LocaleResolver没有注入到Spring中解决方案检查是否通过@Bean将其注入到Spring中,如果没有就加上@Bean注解检查是否指定了Bean的名称,如果没有则检查方法名称。判断名称是否为localeResolverps成功注入图示......
  • C# WPF自定义消息弹窗
    我用的是CaliburnMicro框架,自建框架或者使用其它框架的可自行替换绑定部分即可。效果图: 消息窗体View代码:<Windowx:Class="WpfAppTest.Views.MsgBoxView"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.mi......
  • 09-Vue-概述
    Vue官网:Vue.js(vuejs.org)Avue文档:Date日期|Avue(avuejs.com) 前置工作1)在使用Vue时,我们推荐在你的浏览器上 安装—Vue.js(vuejs.org),它允许你在一个更友好的界面中审查和调试Vue应用。2) 直接下载开发版本的vue.js,并用 <script> 标签引入,Vue 会被注册......
  • 基于ssm+vue.js的在线购书商城系统附带文章和源代码设计说明文档ppt
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我成功案例代码参考数据库参考源码获取前言......