vue自定义指令要点
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自定义指令要点的更多相关文章
- vue自定义指令
Vue自定义指令: Vue.directive('myDr', function (el, binding) { el.onclick =function(){ binding.value(); } ...
- vue 自定义指令的使用案例
参考资料: 1. vue 自定义指令: 2. vue 自定义指令实现 v-loading: v-loading,是 element-ui 组件库中的一个用于数据加载过程中的过渡动画指令,项目中也很少需 ...
- vue自定义指令(Directive中的clickoutside.js)的理解
阅读目录 vue自定义指令clickoutside.js的理解 回到顶部 vue自定义指令clickoutside.js的理解 vue自定义指令请看如下博客: vue自定义指令 一般在需要 DOM 操 ...
- Vue自定义指令报错:Failed to resolve directive: xxx
Vue自定义指令报错 Failed to resolve directive: modle 这个报错有2个原因: 1.指令单词拼错 2.Vue.directive() 这个方法没有写在 new Vue ...
- vue自定义指令clickoutside使用以及扩展用法
vue自定义指令clickoutside使用以及扩展用法 产品使用vue+element作为前端框架.在功能开发过程中,难免遇到使用element的组件没办法满足特殊的业务需要,需要对其进行定制,例如 ...
- vue自定义指令clickoutside扩展--多个元素的并集作为inside
都是个人理解,如果发现错误,恳请大家批评指正,谢谢.还有我说的会比较啰嗦,因为是以自身菜鸡水平的视角来记录学习理解的过程,见谅. 1.前言 产品使用vue+element作为前端框架.在功能开发过程中 ...
- 每个人都能实现的vue自定义指令
前文 先来bb一堆废话哈哈.. 用vue做项目也有一年多了.除了用别人的插件之外.自己也没尝试去封装指令插件之类的东西来用. 刚好最近在项目中遇到一个问题.(快速点击按钮多次触发多次绑定的方法),于是 ...
- vue自定义指令,比onerror更优雅的方式实现当图片加载失败时使用默认图,提供三种方法
首先,来看下效果图(演示一下图片正常加载与加载失败时的效果) 在线体验地址:https://hxkj.vip/demo/vueImgOnerror/ 一.常规方法解决 我们都知道,img标签支持one ...
- Vue自定义指令使用场景
当你第一次接触vue的时候,一定会使用到其中的几个指令,比如:v-if.v-for.v-bind...这些都是vue为我们写好的,用起来相当的爽.如果有些场景不满足,需要我们自己去自定义,那要怎么办呢 ...
随机推荐
- MOOC(10)- 获取响应中的cookie
- 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 ...
- 安装与使用django-restframework
django-restframework 一.安装与使用 1.安装 >: pip3 install djangorestframework 2.使用 在settings.py中注册: INSTA ...
- Invalid action class configuration that references an unknown class解决方案
Sturts2整合后时出现诡异的异常: java.lang.RuntimeException: Invalid action class configuration that references a ...
- js引入的几种简单写法
[方法一] <script> function loadScript() { var script = document.createElement(" ...
- HDU-2802-F(N)
看到这题讨论版里有说用公式的有说用循环节的,但是个人觉得这两种方法都不靠谱,比赛场上做这种题能直接推出公式需要很强数学功底,而循环节的方法如果循环节比较大就不太好发现了.这种已知通项公式的题还是用矩阵 ...
- Trie树的插入,查前缀,查单词,删前缀和删单词。
这个Trie原先用C++就敲得很熟了,看了蓝桥杯的视频后学会把一个功能这样封装起来,以后用的时候就很爽可以直接调用了,所以就用Java写了: public class Trie { private f ...
- Docker的网络类型
四种网络类型: None:不为容器配置任何网络功能,--net=noneContainer:与另一个运行中的容器共享Network Namespace,--net=container:containe ...
- 关于JavaScript中的基本类型
1.在JavaScript的数据中包含以下两种 1 基本类型 Number.Boolean.String.NULL.Undefined 以及ES6的 Symbol 2 引用类型 Object.Arra ...
- Memcached Client 使用手册
Memcached Client 使用手册 Author: cenwenchu Email: wenchu.cenwc@alibaba-inc.com Blog:http://blog.csdn.ne ...