Vue自定义指令及使用

2023-11-18

一、什么是指令

学习 vue 的时候肯定会接触指令,那么什么是指令呢?

  • 在 vue 中提供了一些对于页面和数据更为方便的输出,这些操作就叫做指令,以 v-xxx 表示,比如 html 页面中的属性<div
    v-xxx /div>
  • 比如在 angular 中 以 ng-xxx 开头的就叫做指令
  • 指令中封装了一些 DOM 行为,结合属性作为一个暗号,暗号有对应的值,根据不同的值,会进行相关 DOM
    操作的绑定,即可以进行一些模板的操作

vue中常用的一些内置v-xxx指令

  • v-text:元素的 innerText 属性,只能用在双标签中, 和{{ }}效果是一样的,使用较少
  • v-html:元素的 innerHTML,其实就是给元素的 innerHTML 赋值
  • v-show:元素的显示与隐藏,基于 css 样式的切换。如果确定要隐藏,会给元素的 style 加上display: none
  • v-if:元素的插入和移除操作,相当于对元素的销毁和创建。如果表达式的值为 false,会留下一个 <!---- 作为标记,若未来
    v-if 的值是 true 了,就在这里插入元素(如果 if 有 else 就不要单独留坑了)。
  • v-else-if:前一个相邻元素必须有 v-if 或 v-else-if
  • v-else:前一个相邻元素必须有 v-if 或 v-else-if,如果 v-if 和 v-else-if 都有对应的表达式,则
    v-else 可以直接写
  • v-for:用于循环渲染一组数据(数组或对象)。必须使用特定语法:v-for=“alias in expression”。注:当
    v-for 和 v-if 同处于一个节点时,v-for 的优先级比 v-if 更高。即 v-if 将运行在每个 v-for循环中
  • v-on:主要用来监听 dom 时间,然后执行一些操作。简写为【@】
  • v-model:用于 input/textarea 等表单控件上创建双向数据绑定。
  • v-bind:动态的绑定一个或多个属性,常用于绑定 class,style,href 等。
  • v-once:组件和元素只渲染一次,当数据发生变化,也不会重新渲染。

二、自定义指令的钩子函数

Vue 提供了自定义指令的5个钩子函数:

bind:指令第一次绑定到元素时调用,只执行一次。在这里可以进行一次性的初始化设置。
inserted:被绑定的元素,插入到父节点的 DOM 中时调用(仅保证父节点存在)。
update:组件更新时调用。
componentUpdated:组件与子组件更新时调用。
unbind:指令与元素解绑时调用,只执行一次。

注意:

1、除 update 与 componentUpdated 钩子函数之外,每个钩子函数都含有 el、binding、vnode 这三个参数
2、在每个函数中,第一个参数永远是 el, 表示被绑定了指令的那个 dom 元素,这个el 参数,是一个原生的 JS 对象
   所以 Vue 自定义指令可以用来直接和 DOM 打交道
3、binding 是一个对象,它包含以下属性:name、value、oldValue、expression、arg、modifiers
4、oldVnode 只有在 update 与 componentUpdated 钩子中生效
5、除了 el 之外,binding、vnode 属性都是只读的

钩子函数说白了也就是生命周期,即当一个指令绑定到一个元素上时,这个指令内部有5个生命周期事件函数。接下来创建一个案例来看看这几个钩子函数的触发情况:

<p v-test>这是一段文字</p>export default {
    ... ...
    directives: {
        test: {
              bind () {
                console.log('bind')
              },
              inserted () {
                console.log('inserted')
              },
              update () {
                console.log('update')
              },
              componentUpdated () {
                console.log('componentUpdated')
              },
              unbind () {
                console.log('unbind')
              }
        }
    }
}

在这里插入图片描述

	bind():当指令绑定在 HTML 元素上时触发
	inserted():当指令绑定的元素插入到父节点中的时候触发
	update():当指令绑定的元素状态/样式、内容(这里指元素绑定的 vue 数据) 发生改变时触发
	componentUpdated():当 update() 执行完毕之后触发
	unbind():当指令绑定的元素从 dom 中删除时触发

举几个应用场景的栗子:
1、输入框自动获取焦点(官方示例)。
2、点击下拉菜单以外的区域隐藏菜单。
3、输入的邮箱、电话的校验。

上面这几个场合,在做项目的时候可以用其他方法代替,但是 vue 自定义指令能做到一处定义,全局调用,使得代码简洁高效,更便于维护。

指令的注册方式和「过滤器」「混入」「组件」注册的方式一样都分为两种:一是全局注册,二是局部注册。

三、全局指令

// 给元素添加随机背景
<div v-bgcolor></div>
   
Vue.directive('bgcolor', {
    bind: function(el, binding, vnode) {
        el.style.backgroundColor = "#" + Math.random().toString(16).slice(2,8);
    }
})

注意:在定义的时候,指令的名称前面不需要加 v- 前缀,在调用的时候,必须在指定的名称前加上 v-前缀来进行调用

四、局部指令

// 和data, methods同级
methods: {},
directives: {
    bgcolor: {
         bind: function(el, binding) {
            el.style.backgroundColor = "#" + Math.random().toString(16).slice(2,8);
        }
    }
}

我个人更倾向于使用全局注册的方式,因为既然已经使用了自定义指令,应该是通用的可复用的。所以提供整个项目使用的指令才更有价值,而不仅仅只限于某个组件内部。如果单一地方使用直接把功能搂出来就行了,何必费这力气。

五、带参数的自定义指令

<div v-bgcolor='{color: 'orange'}'></div>

Vue.directive('bgcolor', {
    bind: function(el, binding) {
        el.style.backgroundColor = binding.value.color;
    }
})

六、函数简写

如果想在 bind 和 update 时触发相同行为,而不关心其它的钩子,可以这样写:

// 全局
Vue.directive('bgcolor', function (el, binding) {
      el.style.backgroundColor = binding.value
})

// 局部
directives: {
    bgcolor: (el, binding) => {
        el.style.backgroundColor = binding.value  
    }
}

七、应用实例

熟悉指令的创建方式与参数之后,我们就用它来创建两个实际案例。

1、通过指令来实现点击空白处子菜单隐藏的功能,具体代码如下:

// clickOutside.js
export default {
    bind (el, binding) {
        const self = {} // 定义一个私有变量,方便在unbind中可以解除事件监听
        self.documentHandler = (e) => {
            if (el.contains(e.target)) { // 这里判断绑定的元素是否包含点击元素,如果包含则返回
                return false
            }
            if (binding.value) { // 判断指令中是否绑定了值
                binding.value(e) // 如果绑定了函数则调用那个函数,此处 binding.value就是handleClose方法
            }
            return true
        }
        document.addEventListener('click', self.documentHandler)
    },
    unbind (el) {
        // 解除事件监听
        document.removeEventListener('click', self.documentHandler)
        delete self.documentHandler
    }
}

在组件中使用:

<template>
    <div>
        <div v-show="isShow" v-clickoutside="handleClickOutside" @click="showOrHide">
            子菜单 ... 
        </div>
    </div>
</template><script>
    import clickoutside from './js/clickOutside'
    
    export default {
        ... ...
        directives: {
            clickoutside
        },
        data() {
            return {
                isShow: true,
            };
        },
        methods: {
            handleOutsideClick () {
                this.isShow = false
            }
        }
    }
</script>

2、自定义指令来优化图片的加载:图片在加载过程中,未加载完成时使用灰色背景占位,图片加载完后直接显示

<template>
    <div>
        <!-- 参数不可以直接填写url地址-->
        <img v-imgUrl='url' /> 
    </div>
</template><script>
    export default {
        data () {
            return {
                url: '../src/assets/logo.png'
            }
        }
    }
</script>

// 全局注册
Vue.directive('imgUrl', function (el, binding) {
    el.style.backgroundColor = '#FEFEFE' //设置背景颜色
    var img = new Image()
    img.src = binding.value // binding.value 指令后的参数
    img.onload = function () {
        el.style.backgroundColor = ''
        el.src = binding.value
    }
})

3、防抖

export default (vue) => {
  /**
   * 绑定方法
   * @param {Object} el - The element the directive is bound to.
   * @param {Object} binding - An vue directive object
   */
   vue.directive('debounce', { //防抖函数指令
      inserted: function (el, binding) {
        let timer
        el.addEventListener("click", (e) => {
          if (timer) {
            clearTimeout(timer);
          }
          timer = setTimeout(() => {
          //关键点:vue 的自定义指令传递的参数binding 如果是一个函数,则通过      binding.value()来执行,通过上述示例,还可以传递比如事件, 绑定对象之类的
            binding.value();
          }, 500);
        });
      }
   })
}
// main.js
import Debounce from './directives/debounce.js' //防抖自定义指令
Debounce(Vue)
<i class='iconfont icon-sousuo' v-debounce.prevent.stop="searchClick"></i>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Vue自定义指令及使用 的相关文章

  • 应用程序关闭时监听 firebase 数据库更改

    我正在使用 firebase 创建一个 Ionic 2 应用程序 当应用程序关闭时 即在前台 后台和终止 我需要一种方法来侦听数据库更改 特别是在 child added 上 基本上 我想使用 WebRTC 在应用程序内拨打电话 例如 Wh
  • 如何使用鼠标单击选择多个项目?

    This is the default jQueryUI display as a Grid Layouts demo here http jqueryui com demos selectable display grid I can s
  • Promise.all 返回一个未定义的数组并在完成之前解析

    我在返回数组的函数时遇到问题undefined 这是代码 classMethods getQueries function models dbId dateStart dateEnd return new Promise function
  • 如何获取数组中对象的属性名称?

    这是我的数组 var testeArray name Jovem1 esteira Macaco name Jovem esteira Doido horse Chimbinha 从上面 我想得到一个像这样的数组 var propertyN
  • React 和 Leaflet 结合的好方法

    我正在开发一个将 React 和 Leaflet 结合起来的项目 但我必须说我在语义方面遇到了一些困难 由于大部分内容都是由 Leaflet 直接管理的 我不知道将 Leaflet 映射实例添加为 React 组件中的状态是否有意义 当涉及
  • 仅返回 JavaScript 字符串中最后一个下划线之前的文本

    如果我有一个像这样的字符串 var str Arthropoda Arachnida Zodariidae Habronestes hunti 如何获取最后一个下划线之前的字符串的第一部分 在这种情况下我只想 Arthropoda Arac
  • 如何从回调函数中获取值

    我对 javascript 比较陌生 并且面临一些困难 我有两个 java 脚本文件 如下所示 我无法获取变量的值条目标题在 getRss 函数内并将其存储在变量内Rss1 标题 and Rss2 标题 创建一个全局变量并将其分配给条目标题
  • 是否可以从“GET”请求中检索 MS/延迟? (Javascript/Jquery)

    我目前正在使用 jquery 发出一些 getjson 请求 他们是获取请求 GET http localhost MySite JSON http localhost MySite JSON 现在您可以在 Firebug 中观看请求的触发
  • 如何切换整个页面的深色主题?

    我已经成功地在 html 和 Flask 中按下复选框时切换深色主题和浅色主题 但是我怎样才能让深色主题覆盖整个页面 而不仅仅是一些 div 元素呢 边距仍然是浅色主题 CSS代码如下 container display flow widt
  • 如何使 Loopback 模型事件起作用?

    我尝试过一个例子http apidocs strongloop com loopback model http apidocs strongloop com loopback model MyModel on changed functio
  • JavaScript 中的自定义“确认”对话框?

    我一直在开发一个使用自定义 模式对话框 的 ASP net 项目 我在这里使用吓人引号 因为我知道 模式对话框 只是我的 html 文档中的一个 div 它被设置为出现在文档其余部分的 顶部 而不是真正意义上的模式对话框 在网站的许多部分
  • 如何为 chrome 和 ie favicon(加载指示器)设置动画

    我的 PM 有一个要求 将图标更改为动画加载图像 仅当我将 link href 指向 gif 文件时 它才适用于 Firefox 我做了一些研究 发现 chrome 不支持动画图标 但wiki https en wikipedia org
  • 需要了解Javascript函数提升示例

    我阅读了 Javascript 提升的概念 它非常令人困惑 但我看到了一些示例并了解了提升的实际作用 所以基本上 提升是 JavaScript 的默认行为 即将所有声明移动到当前作用域的顶部 当前脚本或当前函数的顶部 但我无法理解以下实现
  • 不用AJAX,前台同步拖放文件上传?

    我有一个定期的网站
  • 如何在 ES6 类中使用静态变量?

    我正在尝试在 es6 中使用静态变量 我想声明一个静态变量count in Animal类并增加它 但是 我无法通过声明静态变量static count 0 所以我尝试了另一种方法 class Animal constructor this
  • 如何使用 jQuery AJAX 和 JSON 通过 Bootbox 确认表单提交

    我正在使用一个网络应用程序工作Spring MVC 我试图在提交表单之前显示一个确认对话框Bootbox 但我收到 500 内部服务器错误 这是我的表格
  • 使用 Java 进行 AES 加密并使用 Javascript 进行解密

    我正在制作一个需要基于 Java 的 AES 加密和基于 JavaScript 的解密的应用程序 我使用以下代码作为基本形式进行加密 public class AESencrp private static final String ALG
  • CasperJS:如何单击所有选定的按钮?

    我正在尝试使用 CasperJS 作为网络抓取工具 并且有一个带有按钮的页面 单击该按钮将加载数据 因此 我想先单击所有这些按钮 然后等待 然后再实际进行查询以获取所有必要的数据 问题是对于 Casper casper thenClick
  • 错误:Javascript 上的 [object Object]

    当我在 Firebug 中运行下面的 javascript 时 我不断收到错误 我已经尝试更改多项内容 但它仍然输出错误 我正在使用 api 从 XML 检索信息 然后将其输出到屏幕上 但我不断收到对象错误 有人能看出为什么吗 任何帮助表示
  • jQuery 存储类型未定义

    我用了一个jQuery 存储 https ui5 sap com api jQuery sap storage存储数据 oStore jQuery sap storage jQuery sap storage Type local oSto

随机推荐

  • C#基础知识整理四

    上一个知识点整理 已经整理到了结构体方面了 顺便把访问修饰符也一起整理了 今天继续向下整理知识点 今天来了解一下类和面向对象的知识 1 类 什么是类 简单来说就是分类 他是描述具有相同特征 属性 和行为 方法 的抽象就是类 他是用关键字cl
  • Redis中的Hash

    1 前言 本篇博客将介绍Redis中五大类型之一的Hash类型及一些其常用命令 Reids中的Hash是一个键值对类型的集合 类似于Java里面的Map
  • 参数估计

    百度百科解释 参数估计 parameter estimation 是根据从总体中抽取的样本估计总体分布中包含的未知参数的方法 人们常常需要根据手中的数据 分析或推断数据反映的本质规律 即根据样本数据如何选择统计量去推断总体的分布或数字特征等
  • VirtualBox没有64位选项,无法安装64位的解决方法 感谢源作者

    昨天碰到了一个让我惊奇的问题 以前从来没有碰到过 早些年一直用 VM 都是草民肯定买不起VM授权 都是各种的破解版 对吧 这几年vm的破解几乎没有了 反正也不怎么好用就一直用VirtualBox 但是昨天竟然没有办法现在64系统 如果不能安
  • JS使用showModalDialog弹出窗口获得弹出窗口设定的值

    父窗口 hello html
  • ES 搜索3 (查找多个精确值)

    查找多个精确值 term 查询对于查找单个值非常有用 但通常我们可能想搜索多个值 如果我们想要查找价格字段值为 20 或 30 的文档该如何处理呢 不需要使用多个 term 查询 我们只要用单个 terms 查询 注意末尾的 s terms
  • ORACLE数据库怎样查看当前的SID

    方法一 echo ORACLE SID 方法二 select from V database
  • 【自用】深度学习工作站安装ubuntu 18.04 LTS系统

    工作站配置 自己组装的 主板 华硕Z790P PCIE插槽间距大 可以装双显卡 CPU i5 13600KF 内存 32 G 显卡 GTX 2080 Ti 魔改版 22G 存储 1T SSD 8T机械硬盘 系统 ubuntu 18 04 L
  • storm教程(三):用Java开发storm

    1 操作模式 开始之前 有必要了解一下Storm的操作模式 有下面两种方式 本地模式 在本地模式下 Storm拓扑结构运行在本地计算机的单一JVM进程上 这个模式用于开发 测试以及调试 因为这是观察所有组件如何协同工作的最简单方法 在这种模
  • IOCTL函数用法详解

    ioctl是设备驱动程序中对设备的I O通道进行管理的函数 所谓对I O通道进行管理 就是对设备的一些特性进行控制 例如串口的传输波特率 马达的转速等等 它的调用个数如下 int ioctl int fd ind cmd 其中fd是用户程序
  • 使用深度优先搜索查找图中的路径(java)

    package depthfirstpaths import edu princeton cs algs4 Graph import edu princeton cs algs4 Stack public class DepthFirstP
  • php mysql替换数据库中出现过的所有域名实现办法 (原)

    一般新的项目上线或域名必须要更改的时候 有些数据库存的图片或者文件地址带域名的要全部改 恰巧呢 数据库表超级多 恰巧呢 又刚做了接盘侠 啥也不知道 就给你连接数据库让你改 头大不头大 我这个接盘侠上任第一天就遇上了这问题 当拿到将近1G的数
  • Thinkphp 3.2 模型View 里面使用时间戳,在模板中输出时间戳

    很简单 只需要一个代码就能搞定 time 我是这样运用的 这样子做能保证一直更新 Css文件 保证整个布局的及时更新 跟 有效性
  • Android智能下拉刷新框架-SmartRefreshLayout

    框架 下拉刷新控件还能框架化 智能又怎么回事 二话不多少先上Demo效果图 咱们再来探个究竟 Github 传送门注意 本文仅仅是博客文章 主要用于项目介绍和宣传 由于发布时间关系 部分内容已经过期 详细使用文档请跳转 github Dem
  • 大数据毕设 基于python的疫情爬虫分析可视化系统

    文章目录 0 前言 1 课题背景 2 实现效果 3 Flask框架 4 Echarts 5 爬虫 0 前言 这两年开始毕业设计和毕业答辩的要求和难度不断提升 传统的毕设题目缺少创新和亮点 往往达不到毕业答辩的要求 这两年不断有学弟学妹告诉学
  • uniapp表单密码校验:判断两次密码输入是否一致

    uniapp表单密码校验 无需使用自定义validator进行校验 使用uniapp文档内自带的this u test object value password 即可
  • ORA-01536: 超出表空间 'YYPART' 的空间限额

    ORA 01536 超出表空间 YYPART 的空间限额 author skatetime 2008 08 01 现象 研发提示空间不够用 日志显示 ORA 01536 超出表空间 YYPART 的空间限额 解决 alter user sk
  • Redis之十大类型(三)(上)

    redis是k v键值对进行存储 这里的数据类型是value的数据类型 key的类型都是字符串 keys 当前库的所有key exists key 判断某个key是否存在 type key 查看你的key是什么类型 del key 删除指定
  • 华为OD机试 - 去除多余空格(Java)

    题目描述 去除文本多余空格 但不去除配对单引号之间的多余空格 给出关键词的起始和结束下标 去除多余空格后刷新关键词的起始和结束下标 条件约束 1 不考虑关键词起始和结束位置为空格的场景 2 单词的的开始和结束下标保证涵盖一个完整的单词 即一
  • Vue自定义指令及使用

    一 什么是指令 学习 vue 的时候肯定会接触指令 那么什么是指令呢 在 vue 中提供了一些对于页面和数据更为方便的输出 这些操作就叫做指令 以 v xxx 表示 比如 html 页面中的属性 div div div gt 比如在 ang