vue自定义指令的基础使用这里就不阐述,看官网文档:https://cn.vuejs.org/v2/guide/custom-directive.html

本文用一个实例描述自定义指令的要点,自定义一个数据上报的指令。

你可能会这样写demo:

// 自定义v-datacenter命令埋点,点击节点发送埋点数据
// demo : <div v-datacenter="{ei: 'learning_center_click'}">进入学习中心</div>
const dataCenter = function(data){
// 这里处理数据上报
}
Vue.directive('datacenter', {
bind(el, binding) {
     // 或者使用dataset(要注意兼容性):https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/dataset
el._dataCenter = function(el) {
dataCenter(binding.value);
}
el.addEventListener('click', el._dataCenter)
},
unbind(el) {
// 移除监听
el.removeEventListener('click', el._dataCenter);
delete el._dataCenter;
}
})

这个demo对节点的点击做了响应,处理了数据埋点。有什么问题呢?只处理了初次绑定的数据,如果你的数据是通过ajax异步获取的,就可能出现问题,比如

<div v-datacenter="{ei: info.dataEvent}">进入学习中心</div>

其中info.dataEvent最开始是空字符,从后台拉取数据以后info.dataEvent才有值。那么上面的自定义指令中bind中的binding.value的值应当是为空字符。点击上报数据时“ei”的值一直为空字符

改进:

// 自定义v-datacenter命令埋点,点击节点发送埋点数据
// demo : <div v-datacenter="{ei: 'learning_center_click'}">进入学习中心</div>
Vue.directive('datacenter', {
bind(el, binding) {
el._dataCenter = function(el) {
dataCenter(binding.value);
}
el.addEventListener('click', el._dataCenter)
},
update(el, binding) {
// 处理value一开始没有值,后面才有值的情况
if (binding.value && (JSON.stringify(binding.value) !== JSON.stringify(binding.oldValue))) {
// 移除之前的监听
el.removeEventListener('click', el._dataCenter);
delete el._dataCenter; // 新增监听
el._dataCenter = function(el) {
dataCenter(binding.value);
}
el.addEventListener('click'
, el._dataCenter)
}
},

unbind(el) {
// 移除监听
el.removeEventListener('click', el._dataCenter);
delete el._dataCenter;
}
})

添加了update(当所在组件的 VNode 更新时调用),由于update时指令的value可能完全没有改动,所以要判断当值有更改且有效时重新绑定click监听。这样和bind配合就满足了同步/异步的所有场景。

真的就OK了么?显然不是,还有一种异常情况:在特殊情况下(如路由切换),节点既要响应click监听,也要移除节点。unbind就会在响应click监听之前调用。监听在响应之前就被移除,导致失败。

二次改进:

// 自定义v-datacenter命令埋点,点击节点发送埋点数据
// demo : <div v-datacenter="{ei: 'learning_center_click'}">进入学习中心</div>
Vue.directive('datacenter', {
bind(el, binding) {
el._dataCenter = function(el) {
dataCenter(binding.value);
}
el.addEventListener('click', el._dataCenter)
},
update(el, binding) {
// 处理value一开始没有值,后面才有值的情况
if (binding.value && (JSON.stringify(binding.value) !== JSON.stringify(binding.oldValue))) {
// 移除之前的监听
el.removeEventListener('click', el._dataCenter);
delete el._dataCenter; // 新增监听
el._dataCenter = function(el) {
dataCenter(binding.value);
}
el.addEventListener('click', el._dataCenter)
}
},
unbind(el) {
// 移除监听
// 在特殊情况下节点既要响应click,也要移除节点。避免在响应click之前就被移除监听,
// 所以要延时移除,放到下一个宏任务
setTimeout(() => {
el.removeEventListener('click', el._dataCenter);
delete el._dataCenter;
}
)
}
})

要避免在响应监听前监听被移除,所以将移除监听放到下一个宏任务。OK,收工!

如果觉得本文不错,请点击右下方【推荐】!

vue自定义指令要点的更多相关文章

  1. vue自定义指令

    Vue自定义指令: Vue.directive('myDr', function (el, binding) { el.onclick =function(){ binding.value(); } ...

  2. vue 自定义指令的使用案例

    参考资料: 1. vue 自定义指令: 2. vue 自定义指令实现 v-loading: v-loading,是 element-ui 组件库中的一个用于数据加载过程中的过渡动画指令,项目中也很少需 ...

  3. vue自定义指令(Directive中的clickoutside.js)的理解

    阅读目录 vue自定义指令clickoutside.js的理解 回到顶部 vue自定义指令clickoutside.js的理解 vue自定义指令请看如下博客: vue自定义指令 一般在需要 DOM 操 ...

  4. Vue自定义指令报错:Failed to resolve directive: xxx

    Vue自定义指令报错 Failed to resolve directive: modle 这个报错有2个原因: 1.指令单词拼错 2.Vue.directive() 这个方法没有写在 new Vue ...

  5. vue自定义指令clickoutside使用以及扩展用法

    vue自定义指令clickoutside使用以及扩展用法 产品使用vue+element作为前端框架.在功能开发过程中,难免遇到使用element的组件没办法满足特殊的业务需要,需要对其进行定制,例如 ...

  6. vue自定义指令clickoutside扩展--多个元素的并集作为inside

    都是个人理解,如果发现错误,恳请大家批评指正,谢谢.还有我说的会比较啰嗦,因为是以自身菜鸡水平的视角来记录学习理解的过程,见谅. 1.前言 产品使用vue+element作为前端框架.在功能开发过程中 ...

  7. 每个人都能实现的vue自定义指令

    前文 先来bb一堆废话哈哈.. 用vue做项目也有一年多了.除了用别人的插件之外.自己也没尝试去封装指令插件之类的东西来用. 刚好最近在项目中遇到一个问题.(快速点击按钮多次触发多次绑定的方法),于是 ...

  8. vue自定义指令,比onerror更优雅的方式实现当图片加载失败时使用默认图,提供三种方法

    首先,来看下效果图(演示一下图片正常加载与加载失败时的效果) 在线体验地址:https://hxkj.vip/demo/vueImgOnerror/ 一.常规方法解决 我们都知道,img标签支持one ...

  9. Vue自定义指令使用场景

    当你第一次接触vue的时候,一定会使用到其中的几个指令,比如:v-if.v-for.v-bind...这些都是vue为我们写好的,用起来相当的爽.如果有些场景不满足,需要我们自己去自定义,那要怎么办呢 ...

随机推荐

  1. 006.前端开发知识,前端基础CSS(2020-01-21)

    来源:第五天  01盒子水平居中 一.盒子中文字控制: 1.text-align: center; /*可以让盒子内容(文字 行内元素 行内块元素)居中对齐*/ 二.让盒子水平居中对齐: 方法1.ma ...

  2. screen小脚本

    # 创建screen,执行命令,最小化screen #!/usr/bin/env bash screen_name1=$"bdapi" # 检查screen是否存在,等于0.表示s ...

  3. 什么是CDN

    1.什么是cdn    cdn全称是内容分发网络.其目的是让用户能够更快速的得到请求的数据.简单来讲,cdn就是用来加速的,他能让用户就近访问数据,这样就更更快的获取到需要的数据.举个例子,现在服务器 ...

  4. 头次接触wamp服务器、xampp,初次单独使用tomcat部署

    刚刚经过了近两天的接触wamp.xampp.tomcat的时光,真的爽 导师有个网站打不开了,就让我去弄,还有一个网站的后台密码忘了,让我帮忙找回来.我第一感觉就是第一个活不简单,第二个还不简单吗?打 ...

  5. The 2019 Asia Nanchang First Round Online Programming Contest C(cf原题,线段树维护矩阵)

    题:https://nanti.jisuanke.com/t/41350 分析:先将字符串转置过来 状态转移,因为只有5个状态,所以 i 状态到 j 状态的最小代价就枚举[i][k]->[k][ ...

  6. UTF虚拟对象

    虚拟对象: 虚拟对象是为了让UFT识别某些不能识别的控件,把这些控件的范围定义为虚拟对象. 新建虚拟对象 管理虚拟对象 创建虚拟对象之后可通过菜单tools-Virutal Objects-Virut ...

  7. 限制IP每分钟访问10次

    转载:https://www.jianshu.com/p/d1326ab657ff IP请求限制,之前用过redis的set设置时间戳一分钟过期:也用过nginx的IP限流配置.前者,没法解决“用户在 ...

  8. HttpClient学习笔记

    HttpClient相关的实体类官方文档地址:http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/ 使用HttpClien ...

  9. MOOC(7)- case依赖、读取json配置文件进行多个接口请求-封装mock(9)

    封装mock # -*- coding: utf-8 -*- # @Time : 2020/2/12 8:51 # @File : mock_demo_9.py # @Author: Hero Liu ...

  10. nodejs express 框架 上传文件

    web 项目应用express4.0框架 html 表单post 文件上传失败,后端无法获取提交文件 express不支持文件上传. 方式一 若是图片,可以将图片转码为BASE64上传 前端框架ang ...