使用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)
    })
  },
})
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值