首页 web前端 Vue.js 分享一些Vuejs中常用的自定义指令(总结)

分享一些Vuejs中常用的自定义指令(总结)

Jul 08, 2021 am 10:56 AM
vue.js 自定义指令

在Vuejs中,自定义一些指令对底层DOM进行操作。下面本篇文章总结分享一些常用的自定义指令代码,可以直接使用,提高开发效率!

分享一些Vuejs中常用的自定义指令(总结)

【相关推荐:《vue.js教程》】

1、元素点击范围扩展指令 v-expandClick

使用该指令可以隐式的扩展元素的点击范围,由于借用伪元素实现,故不会影响元素在页面上的排列布局。

可传入的参数为:上右下左扩展的范围,单位 px,默认向外扩展 10px。指令的代码如下:

export default function (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)
    }
}
登录后复制

参数 Attributes:

1.png

然后你可以在模板中任何元素上使用新的 v-expandClick property,如下:

<div v-expandClick="20,30,40,50" @click="glabClickoutside"> 点击范围扩大</div>
登录后复制

2、文本内容复制指令 v-copy

使用该指令可以复制元素的文本内容(指令支持单击复制 v-copy、双击复制 v-copy.dblclick、点击icon复制 v-copy.icon 三种模式),不传参数时,默认使用单击复制。

指令的代码如下:

export default {
  bind (el, binding) {
    // 双击触发复制
    if (binding.modifiers.dblclick) {
      el.addEventListener(&#39;dblclick&#39;, () => handleClick(el.innerText))
      el.style.cursor = &#39;copy&#39;
    }
    // 点击icon触发复制
    else if (binding.modifiers.icon) {
      if (el.hasIcon) return
      const iconElement = document.createElement(&#39;i&#39;)
      iconElement.setAttribute(&#39;class&#39;, &#39;el-icon-document-copy&#39;)
      iconElement.setAttribute(&#39;style&#39;, &#39;margin-left:5px&#39;)
      el.appendChild(iconElement)
      el.hasIcon = true
      iconElement.addEventListener(&#39;click&#39;, () => handleClick(el.innerText))
      iconElement.style.cursor = &#39;copy&#39;
    }
    // 单击触发复制
    else {
      el.addEventListener(&#39;click&#39;, () => handleClick(el.innerText))
      el.style.cursor = &#39;copy&#39;
    }
  }
}

function handleClick (text) {
  // 创建元素
  if (!document.getElementById(&#39;copyTarget&#39;)) {
    const copyTarget = document.createElement(&#39;input&#39;)
    copyTarget.setAttribute(&#39;style&#39;, &#39;position:fixed;top:0;left:0;opacity:0;z-index:-1000;&#39;)
    copyTarget.setAttribute(&#39;id&#39;, &#39;copyTarget&#39;)
    document.body.appendChild(copyTarget)
  }

  // 复制内容
  const input = document.getElementById(&#39;copyTarget&#39;)
  input.value = text
  input.select()
  document.execCommand(&#39;copy&#39;)
  // alert(&#39;复制成功&#39;)
}
登录后复制

参数 Attributes:

2.png

然后你可以在模板中任何元素上使用新的 v-copy property,如下:

<div v-copy> 单击复制 </div>
<div v-copy.dblclick> 双击复制 </div>
<div v-copy.icon> icon复制 </div>
登录后复制

3、元素全屏指令 v-screenfull
全屏指令,点击元素进行全屏/退出全屏的操作。支持元素后面是否插入 element-ui 的全屏图标 el-icon-full-screen。

指令的代码如下:

import screenfull from &#39;screenfull&#39;

export default {
  bind (el, binding) {
    if (binding.modifiers.icon) {
      if (el.hasIcon) return
      // 创建全屏图标
      const iconElement = document.createElement(&#39;i&#39;)
      iconElement.setAttribute(&#39;class&#39;, &#39;el-icon-full-screen&#39;)
      iconElement.setAttribute(&#39;style&#39;, &#39;margin-left:5px&#39;)
      el.appendChild(iconElement)
      el.hasIcon = true
  }
    el.style.cursor = el.style.cursor || &#39;pointer&#39;
    // 监听点击全屏事件
    el.addEventListener(&#39;click&#39;, () => handleClick())
  }
}

function handleClick () {
  if (!screenfull.isEnabled) {
    alert(&#39;浏览器不支持全屏&#39;)
    return
  }
  screenfull.toggle()
}
登录后复制

参数 Attributes:

3.png

然后你可以在模板中任何元素上使用新的 v-screenfull property,如下:

<div v-screenfull.icon> 全屏 </div>
登录后复制

4、元素说明指令 v-tooltip

为元素添加说明,如同 element-ui 的 el-tooltip(问号 icon 在鼠标覆盖后,展示说明文字)。

4.png

指令的代码如下:

import Vue from &#39;vue&#39;
export default function (el, binding) {
    if (el.hasIcon) return
    const iconElement = structureIcon(binding.arg, binding.value)
    el.appendChild(iconElement)
    el.hasIcon = true
}

function structureIcon (content, attrs) {
    // 拼接绑定属性
    let attrStr = &#39;&#39;
    for (let 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
}
登录后复制

参数 Attributes:

5.png

然后你可以在模板中任何元素上使用新的 v-tooltip property,如下:

<div v-tooltip:content=&#39;tootipParams&#39;> 提示 </div>
登录后复制

举例:

<div v-tooltip:提示内容为XXX1> 提示1</div>
<div v-tooltip:提示内容为XXX=&#39;tootipParams&#39;> 提示2 </div>
登录后复制

为指令传入 element-ui 支持的参数:

data() {
    return {
        tootipParams: {
            placement: &#39;top&#39;,
            effect: &#39;light&#39;,
        }
    }
}
登录后复制

5、文字超出省略指令 v-ellipsis

使用该指令当文字内容超出宽度(默认 100 px)时自动变为省略形式。等同于使用 css:

width: 100px;
whiteSpace: nowrap
overflow: hidden;
textOverflow: ellipsis;
登录后复制

使用指令效果:

6.png

指令的代码如下:

export default function (el, binding) {
    el.style.width = binding.arg || 100 + &#39;px&#39;
    el.style.whiteSpace = &#39;nowrap&#39;
    el.style.overflow = &#39;hidden&#39;;
    el.style.textOverflow = &#39;ellipsis&#39;;
}
登录后复制
登录后复制

参数 Attributes:

7.png

然后你可以在模板中任何元素上使用新的 v-ellipsis property,如下:

<div v-ellipsis:100> 需要省略的文字是阿萨的副本阿萨的副本阿萨的副本阿萨的副本</div>
登录后复制

6、回到顶部指令 v-backtop
使用该指令可以让页面或指定元素回到顶部。

可选指定元素,如果不指定则全局页面回到顶部。可选在元素偏移多少 px 后显示 backtop 元素,例如在滚动 400px 后显示回到顶部按钮。

8.png

指令的代码如下:

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

参数 Attributes:

9.png

然后你可以在模板中任何元素上使用新的 v-backtop property,如下表示在 id 为 app 的元素滚动 400px 后显示绑定指令的元素:

<div  v-backtop:app="400"> 回到顶部 </div>
登录后复制

也可以这样使用,表示为一直显示绑定指令的元素,并且是全局页面回到顶部:

<div  v-backtop> 回到顶部 </div>
登录后复制

7、空状态指令 v-empty

使用该指令可以显示缺省的空状态。可以传入默认图片(可选,默认无图片)、默认文字内容(可选,默认为暂无数据)、以及标示是否显示空状态(必选)。

10.png

指令的代码如下:

import Vue from "vue";
export default {
  update (el, binding, vnode) {
    el.style.position = el.style.position || &#39;relative&#39;
    const { offsetHeight, offsetWidth } = el
    const { visible, content, img } = binding.value
    const image = img ? `<img src="${img}" height="30%" width="30%"></img>` : &#39;&#39;
    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 || &#39;暂无数据&#39;}</div>
      </div>
    </div>`
    })
    const component = new empty().$mount().$el
    if (visible) {
      el.appendChild(component)
    } else {
      el.removeChild(el.lastChild)
    }
  },
}
登录后复制

参数 Attributes:

11.png

然后你可以在模板中任何元素上使用新的 v-empty property,如下传入对象 emptyValue:

<div style="height:500px;width:500px" v-empty="emptyValue"> 原本内容
登录后复制

需要传入一个参数对象,例如显示文字为:暂无列表,图片路径为 ../../assets/images/blue_big.png,控制标示 visible:

emptyValue = {
  content: &#39;暂无列表&#39;,
  img: require(&#39;../../assets/images/blue_big.png&#39;),
  visible: true,
},
登录后复制

8、徽标指令 v-badge

使用该指令在元素右上角显示徽标。

支持配置徽标的背景颜色、徽标形状;支持传入徽标上显示的数字。

12.png

指令的代码如下:

import Vue from &#39;vue&#39;

const SUCCESS = &#39;#72c140&#39;
const ERROR = &#39;#ed5b56&#39;
const WARNING = &#39;#f0af41&#39;
const INFO = &#39;#4091f7&#39;
const HEIGHT = 20
let flag = false
export default {
  update (el, binding, vnode) {
    const { modifiers, value } = binding
    const modifiersKey = Object.keys(modifiers)
    let isDot = modifiersKey.includes(&#39;dot&#39;)
    let backgroundColor = &#39;&#39;
    if (modifiersKey.includes(&#39;success&#39;)) {
      backgroundColor = SUCCESS
    } else if (modifiersKey.includes(&#39;warning&#39;)) {
      backgroundColor = WARNING
    } else if (modifiersKey.includes(&#39;info&#39;)) {
      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 || &#39;relative&#39;
    const badge = Vue.extend({
      template: targetTemplate
    })
    const component = new badge().$mount().$el
    if (flag) {
      el.removeChild(el.lastChild)
    }
    el.appendChild(component)
    flag = true
  }
}
登录后复制

参数 Attributes:

13.png

然后你可以在模板中任何元素上使用新的 v-badge property,如下:

<div v-badge.dot.info="badgeCount" style="height:50px;width:50px;background:#999"> </div>
登录后复制

9、拖拽指令 v-drag

使用该指令可以对元素进行拖拽。

指令的代码如下:

export default {
  let _el = el
  document.onselectstart = function() {
    return false  //禁止选择网页上的文字
  }
  
  _el.onmousedown = e => {
    let disX = e.clientX - _el.offsetLeft //鼠标按下,计算当前元素距离可视区的距离
    let disY = e.clientY - _el.offsetTop
    document.onmousemove = function(e){     
      let l = e.clientX - disX
      let t = e.clientY - disY;
      _el.style.left = l + "px"
      _el.style.top = t + "px"
    }
    document.onmouseup = e => {
      document.onmousemove = document.onmouseup = null
    }
    return false
  }
}
登录后复制

然后你可以在模板中任何元素上使用新的 v-drag property,如下:

<div v-drag> 支持拖拽的元素 </div>
登录后复制

10、响应缩放指令 v-resize

使用该指令可以响应元素宽高改变时执行的方法。

指令的代码如下:

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

参数 Attributes:

14.png

然后你可以在模板中任何元素上使用新的 v-resize property,如下:

// 传入 resize() 方法
<div v-resize="resize"></div>
登录后复制

11、字符串整形指令 v-format

使用该指令可以修改字符串,如使用 v-format.toFixed 保留两位小数、 v-format.price 将内容变成金额(每三位逗号分隔),可以同时使用,如 v-format.toFixed.price。

例如将数字 243112.331 变成 243112.33,或 243,112.33。

指令的代码如下:

export default {
  update (el, binding, vnode) {
    const { value, modifiers } = binding
    if (!value) return
    let formatValue = value
    if (modifiers.toFixed) {
      formatValue = value.toFixed(2)
    }
    console.log(formatValue)
    if (modifiers.price) {
      formatValue = formatNumber(formatValue)
    }
    el.innerText = formatValue
  },
}



function formatNumber (num) {
  num += &#39;&#39;;
  let strs = num.split(&#39;.&#39;);
  let x1 = strs[0];
  let x2 = strs.length > 1 ? &#39;.&#39; + strs[1] : &#39;&#39;;
  var rgx = /(\d+)(\d{3})/;
  while (rgx.test(x1)) {
    x1 = x1.replace(rgx, &#39;$1&#39; + &#39;,&#39; + &#39;$2&#39;);
  }
  return x1 + x2
}
登录后复制

参数 Attributes:

15.png

然后你可以在模板中任何元素上使用新的 v-format property,如下:

<div v-format.toFixed.price="123333"> 123 </div>
登录后复制

如何使用这些指令?

为了便于管理指令,我们将每个指令都存在于单独的 js 文件中。在项目的 src 下建一个 directives 目录,目录下新建 index.js 文件用于引入并注册指令。

├── src
|  ├── directive
|  |  ├── index.js
|  |  ├── backtop.js
|  |  ├── badge.js
|  |  ├── copy.js
|  |  ├── ellipsis.js
|  |  ├── empty.js
|  |  ├── expandClick.js
|  |  ├── screenfull.js
|  |  └── tooltips.js
|  ├── main.js
登录后复制

举个例子:

directives 目录下新建 ellipsis.js 文件:

export default function (el, binding) {
    el.style.width = binding.arg || 100 + &#39;px&#39;
    el.style.whiteSpace = &#39;nowrap&#39;
    el.style.overflow = &#39;hidden&#39;;
    el.style.textOverflow = &#39;ellipsis&#39;;
}
登录后复制
登录后复制

directives 的 index.js 文件中引入 ellipsis 指令并注册:

import Vue from &#39;vue&#39;
import ellipsis from &#39;./ellipsis&#39; // 引入指令
// import other directives

const directives = {
  ellipsis
  // other directives
}

Object.keys(directives).forEach(name => Vue.directive(name, directives[name]))
登录后复制

最后在 mian.js 中引入 index.js 文件:

import &#39;@/directives/index&#39;
登录后复制
登录后复制

这样就可以正常使用这些指令了:

import &#39;@/directives/index&#39;
登录后复制
登录后复制

更多编程相关知识,请访问:编程入门!!

以上是分享一些Vuejs中常用的自定义指令(总结)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

深入探讨vite是怎么解析.env文件的 深入探讨vite是怎么解析.env文件的 Jan 24, 2023 am 05:30 AM

使用vue框架开发前端项目时,我们部署的时候都会部署多套环境,往往开发、测试以及线上环境调用的接口域名都是不一样的。如何能做到区分呢?那就是使用环境变量和模式。

vue中组件化和模块化有什么区别 vue中组件化和模块化有什么区别 Dec 15, 2022 pm 12:54 PM

组件化和模块化的区别:模块化是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个每个功能模块的职能一致。组件化是从UI界面的角度进行规划;前端的组件化,方便UI组件的重用。

图文详解如何在Vue项目中集成Ace代码编辑器 图文详解如何在Vue项目中集成Ace代码编辑器 Apr 24, 2023 am 10:52 AM

Ace 是一个用 JavaScript 编写的可嵌入代码编辑器。它与 Sublime、Vim 和 TextMate 等原生编辑器的功能和性能相匹配。它可以很容易地嵌入到任何网页和 JavaScript 应用程序中。Ace 被维护为Cloud9 IDE的主要编辑器 ,并且是 Mozilla Skywriter (Bespin) 项目的继承者。

深入聊聊vue3中的reactive() 深入聊聊vue3中的reactive() Jan 06, 2023 pm 09:21 PM

前言:在vue3的开发中,reactive是提供实现响应式数据的方法。日常开发这个是使用频率很高的api。这篇文章笔者就来探索其内部运行机制。

探讨如何在Vue3中编写单元测试 探讨如何在Vue3中编写单元测试 Apr 25, 2023 pm 07:41 PM

当今前端开发中,Vue.js 已经成为了一个非常流行的框架。随着 Vue.js 的不断发展,单元测试变得越来越重要。今天,我们将探讨如何在 Vue.js 3 中编写单元测试,并提供一些最佳实践和常见的问题及解决方案。

Vue中JSX语法和模板语法的简单对比(优劣势分析) Vue中JSX语法和模板语法的简单对比(优劣势分析) Mar 23, 2023 pm 07:53 PM

在Vue.js中,开发人员可以使用两种不同的语法来创建用户界面:JSX语法和模板语法。这两种语法各有优劣,下面就来探讨一下它们的区别和优劣势。

浅析vue怎么实现文件切片上传 浅析vue怎么实现文件切片上传 Mar 24, 2023 pm 07:40 PM

在实际开发项目过程中有时候需要上传比较大的文件,然后呢,上传的时候相对来说就会慢一些,so,后台可能会要求前端进行文件切片上传,很简单哈,就是把比如说1个G的文件流切割成若干个小的文件流,然后分别请求接口传递这个小的文件流。

解析Vue2实现composition API的原理 解析Vue2实现composition API的原理 Jan 13, 2023 am 08:30 AM

自从 Vue3 发布之后,composition API 这个词走入写 Vue 同学的视野之中,相信大家也一直听到 composition API 比之前的 options API 有多好多强,如今由于 @vue/composition-api 插件的发布,Vue2 的同学也可以上车咯,接下来我们主要以响应式的 ref 和 reactive 来深入分析一下,这个插件是怎么实现此

See all articles