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. MOOC(10)- 获取响应中的cookie

  2. The Mean of the Sample Mean|Standard Deviation of the Sample Mean|SE

    7.2  The Mean and Standard Deviation of the Sample Mean Recall that the mean of a variable is denote ...

  3. 安装与使用django-restframework

    django-restframework 一.安装与使用 1.安装 >: pip3 install djangorestframework 2.使用 在settings.py中注册: INSTA ...

  4. Invalid action class configuration that references an unknown class解决方案

    Sturts2整合后时出现诡异的异常: java.lang.RuntimeException: Invalid action class configuration that references a ...

  5. js引入的几种简单写法

    [方法一]   <script>     function loadScript() {        var script = document.createElement(" ...

  6. HDU-2802-F(N)

    看到这题讨论版里有说用公式的有说用循环节的,但是个人觉得这两种方法都不靠谱,比赛场上做这种题能直接推出公式需要很强数学功底,而循环节的方法如果循环节比较大就不太好发现了.这种已知通项公式的题还是用矩阵 ...

  7. Trie树的插入,查前缀,查单词,删前缀和删单词。

    这个Trie原先用C++就敲得很熟了,看了蓝桥杯的视频后学会把一个功能这样封装起来,以后用的时候就很爽可以直接调用了,所以就用Java写了: public class Trie { private f ...

  8. Docker的网络类型

    四种网络类型: None:不为容器配置任何网络功能,--net=noneContainer:与另一个运行中的容器共享Network Namespace,--net=container:containe ...

  9. 关于JavaScript中的基本类型

    1.在JavaScript的数据中包含以下两种 1 基本类型 Number.Boolean.String.NULL.Undefined 以及ES6的 Symbol 2 引用类型 Object.Arra ...

  10. Memcached Client 使用手册

    Memcached Client 使用手册 Author: cenwenchu Email: wenchu.cenwc@alibaba-inc.com Blog:http://blog.csdn.ne ...