vue常见自定义指令

这篇具有很好参考价值的文章主要介绍了vue常见自定义指令。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

常见自定义指令

一、响应缩放指令


  1. 使用
<div v-resize="resize"></div>
  1. 代码
/**
 *  响应缩放指令
 *  @direction 使用该指令可以响应元素宽高改变时执行的方法。
 *  @resize {function} 传入对应resize方法
 *  v-resize="resize"
 **/

export default {
  bind(el, binding) {
    let width = '', height = '';
    function isResize() {
      const style = document.defaultView.getComputedStyle(el);
      if (width !== style.width || height !== style.height) {
        binding.value(); // 执行传入的方法
      }
      width = style.width;
      height = style.height;
    }
    el.__timer__ = setInterval(isResize, 300); // 周期性监听元素是否改变
  },
  unbind(el) {
    clearInterval(el.__timer__);
  }
}

二、元素点击范围扩展指令


  1. 使用
<div v-expandClick="20,30,40,50"></div>
  1. 代码
/**
 *  元素点击范围扩展指令
 *  @direction 使用该指令可以隐式的扩展元素的点击范围,由于借用伪元素实现,故不会影响元素在页面上的排列布局。法。
 *  @top {string} 上扩展的范围,单位 px,默认向外扩展 10px
 *  @right {string} 右扩展的范围,单位 px,默认向外扩展 10px
 *  @bottom {string} 下扩展的范围,单位 px,默认向外扩展 10px
 *  @left {string} 左扩展的范围,单位 px,默认向外扩展 10px
 *  v-expandClick="top, right, bottom, left" (10, 10, 10, 10)
 **/
export default {
  bind(el, binding) {
    const s = document.styleSheets[document.styleSheets.length - 1]
    const DEFAULT = -10 // 默认向外扩展10px
    const ruleStr = `content:"";position:absolute;top:-${top || DEFAULT}px;bottom:-${bottom || DEFAULT}px;right:-${right || DEFAULT}px;left:-${left || DEFAULT}px;`
    const [top, right, bottom, left] = binding.expression && binding.expression.split(',') || []
    const classNameList = el.className.split(' ')
    el.className = classNameList.includes('expand_click_range') ? classNameList.join(' ') : [...classNameList, 'expand_click_range'].join(' ')
    el.style.position = el.style.position || 'relative'
    if (s.insertRule) {
      s.insertRule('.expand_click_range::before' + '{' + ruleStr + '}', s.cssRules.length)
    } else { /* IE */
      s.addRule('.expand_click_range::before', ruleStr, -1)
    }
  }
}

三、文本内容复制指令


  1. 使用
<div v-copy> 单击复制 </div>
<div v-copy.dblclick> 双击复制 </div>
<div v-copy.icon> icon复制 </div>
  1. 代码
/**
 *  文本内容复制指令
 *  @direction 使用该指令可以复制元素的文本内容(指令支持单击复制 v-copy、双击复制 v-copy.dblclick、点击icon复制 v-copy.icon三种模式),不传参数时,默认使用单击复制。
 *  @dblclick {string} dblclick 双击复制文本内容
 *  @icon {string} icon 单击icon复制文本内容
 *  v-copy 单击复制
 *  v-copy.dblclick 双击复制
 *  v-copy.icon icon复制
 **/
export default {
  bind(el, binding) {
    // 双击触发复制
    if (binding.modifiers.dblclick) {
      el.addEventListener('dblclick', () => handleClick(el.innerText))
      el.style.cursor = 'copy'
    } else if (binding.modifiers.icon) { // 点击icon触发复制
      if (el.hasIcon) return
      const iconElement = document.createElement('i')
      iconElement.setAttribute('class', 'el-icon-document-copy')
      iconElement.setAttribute('style', 'margin-left:5px')
      el.appendChild(iconElement)
      el.hasIcon = true
      iconElement.addEventListener('click', () => handleClick(el.innerText))
      iconElement.style.cursor = 'copy'
    } else { // 单击触发复制
      el.addEventListener('click', () => handleClick(el.innerText))
      el.style.cursor = 'copy'
    }
  }
}

四、元素说明指令


  1. 使用
<div v-tooltip:content='tootipParams'> 提示 </div>
  1. 代码
/**
 *  元素说明指令
 *  @direction 为元素添加说明,同 element-ui 的el-tooltip
 *  @content {string} 传给指令的参数
 *  @tooltipParams	 {Object} element-ui 支持的 tooltip属性
 *  v-tooltip:content='tooltipParams'
 **/

import Vue from 'vue'

function structureIcon(content, attrs) {
  // 拼接绑定属性
  let attrStr = ''
  for (const key in attrs) {
    attrStr += `${key}=${attrs[key]} `
  }
  const a = `<el-tooltip content=${content} ${attrStr}><i class="el-icon-question" style="margin:0 10px"></i></el-tooltip>`
  // 创建构造器
  const tooltip = Vue.extend({
    template: a
  })
  // 创建一个 tooltip 实例并返回 dom 节点
  const component = new tooltip().$mount()
  return component.$el
}

export default {
  bind(el, binding) {
    if (el.hasIcon) return
    const iconElement = structureIcon(binding.arg, binding.value)
    el.appendChild(iconElement)
    el.hasIcon = true
  }
}

五、文字超出省略指令


  1. 使用
<div v-ellipsis:100> 需要省略的文字是阿萨的副本阿萨的副本阿萨的副本阿萨的副本</div>
  1. 代码
/**
 *  文字超出省略指令
 *  @direction 使用该指令当文字内容超出宽度。
 *  @width {number} 元素宽度
 *  v-ellipsis:width
 **/

export default {
  bind(el, binding) {
    el.style.width = binding.arg || 100 + 'px'
    el.style.whiteSpace = 'nowrap'
    el.style.overflow = 'hidden';
    el.style.textOverflow = 'ellipsis';
  }
}

六、回到顶部指令


  1. 使用
<div  v-backtop:app="400"> 回到顶部 </div>
  1. 代码
/**
 *  回到顶部指令
 *  @direction 使用该指令可以让页面或指定元素回到顶部。
 *  @id {string} 给需要回到顶部的元素添加的id
 *  @offset {number} 偏移距离为 height 时显示指令绑定的元素
 *  v-backtop:id="offset"
 **/

export default {
  bind(el, binding, vnode) {
    // 响应点击后滚动到元素顶部
    el.addEventListener('click', () => {
      const target = binding.arg ? document.getElementById(binding.arg) : window
      target.scrollTo({
        top: 0,
        behavior: 'smooth'
      })
    })
  },
  update(el, binding, vnode) {
    // 滚动到达参数值才出现绑定指令的元素
    const target = binding.arg ? document.getElementById(binding.arg) : window
    if (binding.value) {
      target.addEventListener('scroll', (e) => {
        if (e.srcElement.scrollTop > binding.value) {
          el.style.visibility = 'unset'
        } else {
          el.style.visibility = 'hidden'
        }
      })
    }
    // 判断初始化状态
    if (target.scrollTop < binding.value) {
      el.style.visibility = 'hidden'
    }
  },
  unbind(el, binding) {
    const target = binding.arg ? document.getElementById(binding.arg) : window
    target.removeEventListener('scroll')
    el.removeEventListener('click')
  }
}

七、拖拽指令


  1. 使用
<div v-drag> 支持拖拽的元素 </div>
  1. 代码
/**
 *  拖拽指令
 *  @direction 使用该指令可以对元素进行拖拽。
 *  v-drag=“[width, height]”
 **/

export default {
  inserted(el, binding) {
    let { value } = binding;
    if (!value || value.length === 0) value = [0, 0]
    el.style.cursor = 'move'
    el.onmousedown = function(e) {
      const disx = e.pageX - el.offsetLeft
      const disy = e.pageY - el.offsetTop
      document.onmousemove = function(e) {
        let x = e.pageX - disx
        let y = e.pageY - disy
        const maxX = document.body.clientWidth - parseInt(window.getComputedStyle(el).width) - value[0]
        const maxY = document.body.clientHeight - parseInt(window.getComputedStyle(el).height) - value[1]
        if (x < 0) {
          x = 0
        } else if (x > maxX) {
          x = maxX
        }

        if (y < 0) {
          y = 0
        } else if (y > maxY) {
          y = maxY
        }

        el.style.left = x + 'px'
        el.style.top = y + 'px'
      }
      document.onmouseup = function() {
        document.onmousemove = document.onmouseup = null
      }
    }
  }
}

八、长按指令


  1. 使用
<div v-longpress="longPress"></div>
  1. 代码
/**
 *  长按指令
 *  @direction 实现长按,用户需要按下并按住按钮几秒钟,触发相应的事件
 *  @longPress {function} 长按的回调
 *  v-longpress="longPress"
 **/

export default {
  bind: function(el, binding, vNode) {
    if (typeof binding.value !== 'function') {
      throw 'callback must be a function'
    }
    // 定义变量
    let pressTimer = null
    // 创建计时器( 2秒后执行函数 )
    const start = (e) => {
      if (e.type === 'click' && e.button !== 0) {
        return
      }
      if (pressTimer === null) {
        pressTimer = setTimeout(() => {
          handler()
        }, 2000)
      }
    }
    // 取消计时器
    const cancel = (e) => {
      if (pressTimer !== null) {
        clearTimeout(pressTimer)
        pressTimer = null
      }
    }
    // 运行函数
    const handler = (e) => {
      binding.value(e)
    }
    // 添加事件监听器
    el.addEventListener('mousedown', start)
    el.addEventListener('touchstart', start)
    // 取消计时器
    el.addEventListener('click', cancel)
    el.addEventListener('mouseout', cancel)
    el.addEventListener('touchend', cancel)
    el.addEventListener('touchcancel', cancel)
  },
  // 当传进来的值更新的时候触发
  componentUpdated(el, { value }) {
    el.$value = value
  },
  // 指令与元素解绑的时候,移除事件绑定
  unbind(el) {
    el.removeEventListener('click', el.handler)
  }
}

九、防抖指令


  1. 使用
 <el-button v-debounce="debounceClick"> 防抖 </el-button>
  1. 代码
/**
 *  防抖指令
 *  @direction 防止按钮在短时间内被多次点击,使用防抖函数限制规定时间内只能点击一次。
 *  @debounceClick {function} 按钮的点击事件
 *  v-debounce="debounceClick"
 **/

export default {
  inserted(el, binding) {
    let timer
    el.addEventListener('keyup', () => {
      if (timer) {
        clearTimeout(timer)
      }
      timer = setTimeout(() => {
        binding.value()
      }, 1000)
    })
  }
}

十、水印指令


  1. 使用
<div v-waterMarker="{text:'版权所有',textColor:'rgba(180, 180, 180, 0.4)', font:'16px Microsoft JhengHei'}"></div>
  1. 代码
/**
 *  水印指令
 *  @direction 给整个页面添加背景水印
 *  @data {Object} 水印文案,颜色,字体
 *  v-waterMarker="{text:'版权所有',textColor:'rgba(180, 180, 180, 0.4)', font:'16px Microsoft JhengHei'}"
 **/

function addWaterMarker(str, parentNode, font, textColor) {
  // 水印文字,父元素,字体,文字颜色
  const can = document.createElement('canvas')
  parentNode.appendChild(can)
  can.width = 200
  can.height = 150
  can.style.display = 'none'
  const cans = can.getContext('2d')
  cans.rotate((-20 * Math.PI) / 180)
  cans.font = font || '16px Microsoft JhengHei'
  cans.fillStyle = textColor || 'rgba(180, 180, 180, 0.3)'
  cans.textAlign = 'left'
  cans.textBaseline = 'Middle'
  cans.fillText(str, can.width / 10, can.height / 2)
  parentNode.style.backgroundImage = 'url(' + can.toDataURL('image/png') + ')'
}

export default {
  bind(el, binding) {
    addWaterMarker(binding.value.text, el, binding.value.font, binding.value.textColor)
  }
}

十一、懒加载指令select


  1. 使用
<el-select v-loadselect="loadmore"></el-select>
  1. 代码
/**
 *  el-select懒加载指令
 *  @direction 下拉框数据较多,需要下拉的时候懒加载数据
 *  @load {function} 懒加载调用方法
 *  v-loadselect="load"
 **/

export default {
  inserted(el, binding) {
    const selectWarpDom = el.querySelector(
      '.el-select-dropdown .el-select-dropdown__wrap'
    )
    selectWarpDom.addEventListener('scroll', function() {
      if (this.scrollHeight - this.scrollTop <= this.clientHeight) {
        binding.value()
      }
    })
  }
}


十二、徽标指令


  1. 使用
<div v-badge.dot.info="10"></div>
>
  1. 代码
/**
 *  徽标指令
 *  @direction 使用该指令在元素右上角显示徽标。
 *  @shape {string} 形状 [normal(正常徽标), dot(仅展示一个点)]
 *  @type {string} 徽标颜色类型 [success, error, info, warning]
 *  @num {number} 懒加载调用方法
 *  v-badge.shape.type="num"
 **/

import Vue from 'vue'

const SUCCESS = '#72c140'
const ERROR = '#ed5b56'
const WARNING = '#f0af41'
const INFO = '#4091f7'
const HEIGHT = 20
let flag = false
export default {
  update(el, binding, vnode) {
    const { modifiers, value } = binding
    const modifiersKey = Object.keys(modifiers)
    const isDot = modifiersKey.includes('dot')
    let backgroundColor = ''
    if (modifiersKey.includes('success')) {
      backgroundColor = SUCCESS
    } else if (modifiersKey.includes('warning')) {
      backgroundColor = WARNING
    } else if (modifiersKey.includes('info')) {
      backgroundColor = INFO
    } else {
      backgroundColor = ERROR
    }

    const targetTemplate = isDot
      ? `<div style="position:absolute;top:-5px;right:-5px;height:10px;width:10px;border-radius:50%;background:${backgroundColor}"></div>`
      : `<div style="background:${backgroundColor};position:absolute;top:-${HEIGHT / 2}px;right:-${HEIGHT / 2}px;height:${HEIGHT}px;min-width:${HEIGHT}px;border-radius:${HEIGHT / 2}px;text-align:center;line-height:${HEIGHT}px;color:#fff;padding:0 5px;">${value}</div>`

    el.style.position = el.style.position || 'relative'
    const badge = Vue.extend({
      template: targetTemplate
    })
    const component = new badge().$mount().$el
    if (flag) {
      el.removeChild(el.lastChild)
    }
    el.appendChild(component)
    flag = true
  }
}

十三、空状态指令


  1. 使用
<div v-empty="emptyValue" style="height:500px;width:500px"> 原本内容 </div>
  1. 代码
/**
 *  空状态指令
 *  @direction 使用该指令可以显示缺省的空状态, 可以传入默认图片(可选,默认无图片)、默认文字内容(可选,默认为暂无数据)、以及标示是否显示空状态(必选)。
 *  @emptyValue  {Object} 懒加载调用方法
 *  @content: '暂无列表', 可选
 *  @img: require('../../assets/images/xxx.png'), 可选
 *  @visible: 'true', 是否显示. 必传
 *  v-empty="emptyValue "
 **/

import Vue from 'vue';
export default {
  update(el, binding, vnode) {
    el.style.position = el.style.position || 'relative'
    const { offsetHeight, offsetWidth } = el
    const { visible, content, img } = binding.value
    const image = img ? `<img src="${img}" height="30%" width="30%">` : ''
    const defaultStyle = 'position:absolute;top:0;left:0;z-index:9999;background:#fff;display:flex;justify-content: center;align-items: center;'
    const empty = Vue.extend({
      template: `<div style="height:${offsetHeight}px;width:${offsetWidth}px;${defaultStyle}">
      <div style="text-align:center">
        <div>${image}</div>
        <div>${content || '暂无数据'}</div>
      </div>
    </div>`
    })
    const component = new empty().$mount().$el
    if (visible) {
      el.appendChild(component)
    } else {
      el.removeChild(el.lastChild)
    }
  }
}

十四、输入框聚焦指令


  1. 使用
<div v-focus></div>
  1. 代码
/**
 *  输入框聚焦指令
 *  @direction 页面加载时,输入框自动聚焦。
 *  v-focus
 **/

export default {
  inserted(el) {
    // 聚焦元素
    el.focus()
  }
}

文章来源地址https://www.toymoban.com/news/detail-474259.html

到了这里,关于vue常见自定义指令的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Vue2.0源码学习】指令篇-Vue自定义指令

    在 Vue 中,除了 Vue 本身为我们提供的一些内置指令之外, Vue 还支持用户自定义指令。并且用户有两种定义指令的方式:一种是使用全局API—— Vue.directive 来定义全局指令,这种方式定义的指令会被存放在 Vue.options[\\\'directives\\\'] 中;另一种是在组件内的 directive 选项中定义专为

    2024年02月09日
    浏览(45)
  • Vue-27、Vue自定义指令

    函数式写法 完整写法 big函数何时被调用? 指令与元素成功绑定时(一上来) 指令所在的模板被重新解析时 注意: 此时 element.focus();不凑效。原因此时指令与元素成功绑定。但是input 并未出现页面。但是当n变化时 element.focus()会生效。 所以函数式写法不完美。 对象式写法

    2024年01月19日
    浏览(38)
  • 【Vue】二:Vue核心处理---vue的其它指令和自定义指令

    v-text:当做文件解析。 v-html:当做 HTML 代码解析。 v-cloak 配置 css 样式来解决胡子的闪现问题。 我们模拟网络延迟的情况下,发现出现了如上的问题。 只渲染一次。之后将被视为静态内容。 带有该指令的标签将不会被编译。 指令的名字 (1)v-不需要写 (2)Vue官方建议指令

    2024年02月08日
    浏览(40)
  • VUE---自定义指令

    自定义指令:自己定义的指令,可以封装一些dom操作,扩展额外功能。可分为全局注册与                        局部注册。 全局注册(main.js中注册): Vue.directive(\\\'指令名称\\\',{         bind(ele,binding) {},  // 只执行一次;DOM渲染之前执行,里面可以进行样式操作       

    2024年01月19日
    浏览(33)
  • Vue 自定义指令

    除了默认设置的核心指令( v-model 和 v-show ), Vue 也允许注册自定义指令。 下面我们注册一个全局指令 v-focus, 该指令的功能是在页面加载时,元素获得焦点: 实例 我们也可以在实例使用 directives 选项来注册局部指令,这样指令只能在这个实例中使用: 实例 钩子函数 指令定义

    2023年04月21日
    浏览(40)
  • 【Vue】自定义指令

            📝个人主页: 五敷有你         🔥系列专栏: Vue ⛺️稳重求进,晒太阳 之前的v-html v-model v-for 等都是内置指令 自定义指令: 自己定义的指令,可以封装一些dom操作,扩展额外功能 操作dom:dom元素.focus() 全局注册:-语法 Vue 自动将我们的 自定义指令添加上了

    2024年02月21日
    浏览(44)
  • vue自定义指令

    Vue.js 提供了自定义指令(Directives)的特性,允许开发者自定义 HTML 标签的行为。自定义指令是 Vue 的一种高级特性,它使你可以扩展 HTML 标签的行为。通过自定义指令,你可以添加、修改或删除元素的某些行为。 vue存在许多的内置指令:如:v-html、v-model、v-for 等等。 那么如

    2024年01月22日
    浏览(48)
  • 【vue2第十三章】自定义指令 自定义v-loading指令

    像 v-html,v-if,v-for都是vue内置指令,而我们也可以封装自定义指令,提升编码效率。 什么是自定义指令? 自己定义的一些指令,可以进行一些dom操作,扩展格外的功能。比如让图片懒加载,让input自动聚焦。 自定义指令又分为全局注册和局部注册。 使用方法则是与内置指令

    2024年02月09日
    浏览(48)
  • Vue怎么设置自定义指令

    在 Vue,除了核心功能默认内置的指令 ( v-model 和 v-show ),Vue 也允许注册自定义指令。它的作用价值在于当开发人员在某些场景下需要对普通 DOM 元素进行操作。 Vue自定义指令有全局注册和局部注册两种方式。先来看看注册全局指令的方式,通过 Vue.directive( id, [definition] ) 方式

    2024年01月19日
    浏览(41)
  • Vue3: 自定义指令

    vue 官方提供了 v-for、v-model、v-if 等常用的内置指令。除此之外vue 还允许开发者自定义指令。 vue 中的自定义指令分为两类,分别是: ⚫ 私有自定义指令 ⚫ 全局自定义指令 在每个 vue 组件中,可以在 directives 节点下声明私有自定义指令。示例代码如下: 在使用自定义指令时

    2024年02月15日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包