使用vue自定义指令写工具函数

news/2024/7/9 23:45:31 标签: vue

vue中有很多v- 前缀的特殊 attribute,这就是vue的指令。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。常见的vue指令有:v-bind、v-on、v-model、v-if、v-show等。但是有些时候vue内置的这些指令并不能满足我们的使用需求,因此vue也允许注册自定义指令,下面讲一下如何注册自定义指令。

一、定义:

// 一、在创建根实例之前 即全局自定义指令

// 一个指令定义对象有如下几个钩子函数:
// bind 只调用一次,指令第一次绑定到元素时调用。可以进行一次性的初始化设置。
// inserted: 被绑定的元素插入父节点的时候调用。
// update: 所在组件更新时调用。
// componentUpdate :所在组件更新后调用。
// unbind: 只调用一次,指令与元素解绑时调用。

// 上述钩子函数会被传入以下参数:
// el:指令所绑定的元素,可以用来直接操作 DOM。
// binding:一个对象,包含以下 property:
//   -name:指令名,不包括 v- 前缀。
//   -value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
//   -expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
//   -arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
//   -modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
// vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。 

// 注意:除了 el 之外,其它参数都应该是只读的,切勿进行修改。

vue.directive('test', {
  bind:(el,binding,vnode) => {
    console.log('test, bind')
  },
  inserted:(el,binding,vnode) => {
    console.log('test, inserted')
  },
  update:(el,binding,vnode) => {
    console.log('test, update')
  },
  componentUpdated:(el,binding,vnode) => {
    console.log('test, componentUpdated')
  },
  unbind:(el,binding,vnode) => {
    console.log('test, unbind')
  },
})
// 如果只想在bind和update时触发回调,那么可以这样写。
vue.directive('test', (el,binding,vnode) => {
  console.log('test')
})

// 二、在一个组件的选项中定义自定义指令 即局部自定义指令
// 完整
directives: {
  test: {
    bind:(el,binding,vnode) => {
      console.log('test, bind')
  	},
  	inserted:(el,binding,vnode) => {
      console.log('test, inserted')
  	},
  	update:(el,binding,vnode) => {
      console.log('test, update')
  	},
  	componentUpdated:(el,binding,vnode) => {
      console.log('test, componentUpdated')
  	},
  	unbind:(el,binding,vnode) => {
      console.log('test, unbind')
  	},
  }
}
// 简写
directives: {
  test: (el,binding,vnode) => {
    console.log('test, bind')
  }
}

使用:

// 在任何元素下都可以使用
<div v-test>test</div>

以下是一些常用的自定义指令,可放入工具函数模块中。

vue.directive('copy', { // 复制文字到剪切板
  bind(el, binding) {
    el.copyValue = binding.value
    el.copyWords = () => {
      if (!el.copyValue) {
        console.log('无复制内容')
        return
      }
      // 动态创建 textarea 标签
      const textarea = document.createElement('textarea')
      // 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
      textarea.readOnly = 'readonly'
      textarea.style.position = 'absolute'
      textarea.style.left = '-9999px'
      // 将要 copy 的值赋给 textarea 标签的 value 属性
      textarea.value = el.copyValue
      // 将 textarea 插入到 body 中
      document.body.appendChild(textarea)
      // 选中值并复制
      textarea.select()
      const result = document.execCommand('Copy')
      if (result) {
        console.log('复制成功')
      }
      document.body.removeChild(textarea)
    }
    // 绑定点击事件
    el.addEventListener('click', el.copyWords)
  },
  // 当传进来的值更新的时候触发
  componentUpdated(el, { value }) {
    el.copyValue = value
  },
  // 指令与元素解绑的时候,移除事件绑定
  unbind(el) {
    el.removeEventListener('click', el.copyWords)
  },
})

vue.directive('long-press', { // 长按识别
  bind (el, binding) {
    // 回调函数
    const longPress = (e) => {
      binding.value(e)
    }
    // 计时器
    let pressTimer = null
    let start = (e) => {
      console.log(e)
      if (pressTimer === null) {
        pressTimer = setTimeout(() => {
          longPress()
        }, 2000)
      }
    }
    // 取消计时器
    let cancel = (e) => {
      console.log(e)
      if (pressTimer !== null) {
        clearTimeout(pressTimer)
        pressTimer = null
      }
    }
    
    // 添加事件监听器
    el.addEventListener('mousedown', start)
    el.addEventListener('touchstart', start)
    // 取消计时器
    el.addEventListener('click', cancel)
    el.addEventListener('mouseout', cancel)
    el.addEventListener('touchend', cancel)
    el.addEventListener('touchcancel', cancel)
  }
})
vue.directive('debounce', { // 防抖
  inserted(el, binding) {
    let timer = null
    el.addEventListener('click', () => {
      if (timer) {
        clearTimeout(timer)
      }
      timer = setTimeout(() => {
        binding.value()
      }, 1000)
    })
  },
})

http://www.niftyadmin.cn/n/1769482.html

相关文章

JVM调优预习(note)

在线调优JVM——GC-turning 前言 马士兵老师公开课真的讲的挺好的&#xff0c;不过自身水平不够&#xff0c;整理一下自己听课的感觉 为什么使用root searching JVM调优 垃圾回收 垃圾&#xff1a;当有一个对象没有任何引用指向 java通过垃圾回收器&#xff0c;一般不需要关…

js中call()、apply()、bind()的使用及实现

使用 call()、apply()、bind()都是用来改变this的指向的。 一、A.a.call(B, x, y) A是一个对象&#xff0c;a是对象A里的方法函数&#xff0c;x和y是a函数的参数&#xff0c;B也是一个对象&#xff0c;但对象B想调用对象A的a方法&#xff0c;那么call()的作用就是改变函数a的t…

三角形最大和问题

题目描述 给一个数组至少三个数&#xff0c;任意选出数组中三个数&#xff0c;求满足三角形的三个数的最大和 例如&#xff1a; 1 2 3 不满足三角形&#xff0c;返回0 1 2 3 4 满足三角形最大和为2349&#xff0c;返回9 package test_26; import java.lang.reflect.Array…

浅克隆与深克隆

浅克隆 一般实现数组克隆的方法都是浅克隆&#xff0c;直接将存储在栈中的值赋值给对应变量&#xff0c;如果是基本数据类型&#xff0c;则直接赋值对应的值&#xff0c;如果是引用类型&#xff0c;则赋值的是地址 方法 slice&#xff1a; let arr2 arr1.slice(0); concat…

Java多线程(切换输入)

多线程 数组1 {1&#xff0c;2&#xff0c;3} 数组2{A&#xff0c;B&#xff0c;C} 要求切换输出结果&#xff1a;1A2B3C package test_26;import java.util.concurrent.locks.LockSupport;class S1 {static Thread t1null,t2null;public static void main(String[] args) {…

Vue的ESLint配置

Vue的ESLint配置 常用规则 // “off”或0&#xff1a;不启用该规则。 // “warn”或1&#xff1a;违反时警告。 // “error”或2&#xff1a;违反时报错。 rules: {"comma-dangle": ["error", "never"], //是否允许对象中出现结尾逗号"no…

如何快速的Github下载超具体操作

How to be quick ——git clone 前言 相信有时会奇怪为什么git clone总是那么的慢呢&#xff1f;主要原因是因为……敲黑板了&#xff0c;保持安静 因为github.global.ssl.fastly.net域名被限制了&#xff0c;不要问三连 那么如何处理这种情况呢&#xff1f;The only thing …

ThreadPoolExecutor的4种拒绝策略(TODO未完成)

ThreadPoolExecutor的4种拒绝策略 问题场景 当加入的任务数量超过一定数目&#xff08;maximumPoolSize BlockingQueue 队列长度&#xff09;&#xff0c;默认情况下会抛出异常。这种情况会造成某些采集、转换错误、遗漏&#xff0c;不符合预期。 期望的结果是&#xff0c;分…