vue自定义指令实现v-tap插件


Posted in Javascript onNovember 03, 2016

放弃jQuery,拥抱MVVM,拥抱组件吧!

vue-touch基于hammer,对于普通简单手势的页面来说过于庞大!
于是想自己实现一个最常用的手势tap。顺着自定义指令和插件文档,昨晚实现了一个v-tap指令,丢出这篇干货。

指令与插件介绍
自定义指令和插件官方文档中也介绍比较简单详细,就不过多介绍。
我先说下本插件就用了三个API,如果大家不了解最好先事先看下文档避免后面的代码看的迷糊。

指令部分
1.update(nVal,oVal)
2.acceptStatement

插件部分
Vue.use()

接着我们需要像写jQuery插件一样学习写Vue插件的格式。

继续官方文档

MyPlugin.install = function (Vue, options) {
 // 1. 添加全局方法或属性
 Vue.myGlobalMethod = ...
 // 2. 添加全局资源
 Vue.directive('my-directive', {})
 // 3. 添加实例方法
 Vue.prototype.$myMethod = ...
}

是不是看的还不太明白?那我们可以直接看作者的插件代码。

;(function () {

 var vueTouch = {}

 vueTouch.install = function (Vue) {

 Vue.directive('touch', {

  isFn: true,
  acceptStatement: true,

  bind: function () {

  },

  update: function (fn) {

  },

  unbind: function () {

  }
 })
 }

 if (typeof exports == "object") {
 module.exports = vueTouch
 } else if (typeof define == "function" && define.amd) {
 define([], function(){ return vueTouch })
 } else if (window.Vue) {
 window.VueTouch = vueTouch
 Vue.use(vueTouch)
 }

})()

我把多余无关代码都删除了,可以发现其实格式就是如此,剩下的就是利用我们自己js的功底直接编写即可。
PS:关于 isFn:true 这个属性,我在文档中没有查到相关信息,个人认为可能是一种注释,代表这个指令是需要fn的expression(这个是指令的表达式,详见指令实例属性)。

Just do it

首先,按照插件格式先写好外层。

;(function() {
 var vueTap = {};
 vueTap.install = function(Vue) {

 };

 if (typeof exports == "object") {
  module.exports = vueTap;
 } else if (typeof define == "function" && define.amd) {
  define([], function(){ return vueTap })
 } else if (window.Vue) {
  window.vueTap = vueTap;
  Vue.use(vueTap);
 }

})();

接着在我们的 vueTap.install 里写我们自己的自定义指令

Vue.directive('tap', {
  isFn : true,
  bind : function() {

  },
  update : function(fn) {

  },
  unbind : function() {},
  isTap : function() {
   //判断是否为tap
  },
  touchstart : function(e,self) {

  },
  touchend : function(e,self) {

  }
 });
};

由于只有update才有参数可传,可以接收到我们expression,于是我把事件绑定处理过程都写在了update里。

PS: 当然也有小伙伴喜欢在这把fn都赋予在this(这里的this是directve实例)上,最后在bind的地方绑定事件。这个我并没有找到规范,还不知道写哪比较好。

update : function(fn) {
 var self = this; //存下this,方便以后用
  //在directive上绑定的属性和方法
  //都可通过self.xxx self.touchstart()获取
  self.tapObj = {}; //初始化我们的tap对象

 if(typeof fn !== 'function') {
 //你别给我搞事!
  return console.error('The param of directive "v-tap" must be a function!');
 }

 self.handler = function(e) { //给当前directive存个handler方便之后调用
  e.tapObj = self.tapObj; 
  //把我们的tap对象赋值给原生event对象上,方便回调里获取参数
  fn.call(self,e);
 };

 //把我们的start和end剥离出来,写在directive上
 //由于只有tap事件,所以我们在move过程就不需要做处理
 this.el.addEventListener('touchstart',function(e) {
  self.touchstart(e,self);
 },false);

 this.el.addEventListener('touchend',function(e) {
  self.touchend(e,self,fn);
 },false);

}

在update很简单,就是一些初始化,事件绑定和给实例赋值的过程。
最后就是isTap,touchstart,touchend的逻辑处理。

isTap : function() {
 var tapObj = this.tapObj;
 return this.time < 150 && Math.abs(tapObj.distanceX) < 2 && Math.abs(tapObj.distanceY) < 2;
},
touchstart : function(e,self) {
 var touches = e.touches[0];
 var tapObj = self.tapObj;
 tapObj.pageX = touches.pageX;
 tapObj.pageY = touches.pageY;
 tapObj.clientX = touches.clientX;
 tapObj.clientY = touches.clientY;
 self.time = +new Date();
},
touchend : function(e,self) {
 var touches = e.changedTouches[0];
 var tapObj = self.tapObj;
 self.time = +new Date() - self.time;
 tapObj.distanceX = tapObj.pageX - touches.pageX;
 tapObj.distanceY = tapObj.pageY - touches.pageY;

 if (self.isTap(tapObj))
  self.handler(e);
}

最后有个大问题,如何能让我们的expression可接受传参?

<ul>
 <li v-for="el in list"
  v-tap="args($index,el,$event)"
   >
  {{el.name}}---{{el.age}}
 </li>
</ul>

那就要在我们的directive上加一个属性acceptStatement:true(详见文档acceptStatement)

总结
写了这个v-tap插件几个心得分享给大家。
1.在update里的this指向是directive实例,而不是vm,也不是dom
2.在directive('name',{}) 对象里可自定义属性和方法。调用就是self.xxx
3.开启自定义指令接受内联语句 acceptStatement:true
4.最后的接口别忘了 Vue.use(obj)
我这里没有对v-tap.stop, v-tap.prevent,v-tap.stop.prevent做处理,大家可以自己实现!也灰常简单。
(我之后会对v-tap进行补充)

最后丢出github地址: https://github.com/MeCKodo/vue-tap

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript下阻止表单重复提交、防刷新、防后退
Aug 17 Javascript
JavaScript修改css样式style
Apr 15 Javascript
JavaScript入门教程(1) 什么是JS
Jan 31 Javascript
浅析vue数据绑定
Jan 17 Javascript
最常见和最有用的字符串相关的方法详解
Feb 06 Javascript
vue.js事件处理器是什么
Mar 20 Javascript
JS实现标签页切换效果
May 04 Javascript
Express之托管静态文件的方法
Jun 01 Javascript
vue生命周期实例小结
Aug 15 Javascript
解决element-ui中下拉菜单子选项click事件不触发的问题
Aug 22 Javascript
js定义类的方法示例【ES5与ES6】
Jul 30 Javascript
微信小程序button标签open-type属性原理解析
Jan 21 Javascript
angular ngClick阻止冒泡使用默认行为的方法
Nov 03 #Javascript
vue.js指令v-for使用及索引获取
Nov 03 #Javascript
vue.js初学入门教程(1)
Nov 03 #Javascript
把json格式的字符串转换成javascript对象或数组的方法总结
Nov 03 #Javascript
AngularJS出现$http异步后台无法获取请求参数问题的解决方法
Nov 03 #Javascript
Centos7 中安装 Node.js v4.4.4
Nov 03 #Javascript
[原创]javascript typeof id==='string'?document.getElementById(id):id解释
Nov 02 #Javascript
You might like
PHP spl_autoload_register实现自动加载研究
2011/12/06 PHP
php实现用于验证所有类型的信用卡类
2015/03/24 PHP
PHP中header用法小结
2016/05/23 PHP
javascript 获取图片尺寸及放大图片
2013/09/04 Javascript
5秒后跳转到另一个页面的js代码
2013/10/12 Javascript
jquery easyui combox一些实用的小方法
2013/12/25 Javascript
javascript 拷贝节点cloneNode()使用介绍
2014/04/03 Javascript
JavaScript onkeypress事件入门实例(按下或按住一个键盘按键)
2014/10/17 Javascript
jquery trigger函数执行两次的解决方法
2016/02/29 Javascript
Bootstrap复选框和单选按钮美化插件(推荐)
2016/11/23 Javascript
js封装成插件_Canvas统计图插件编写实例
2017/09/12 Javascript
详解VUE 数组更新
2017/12/16 Javascript
webpack之devtool详解
2018/02/10 Javascript
微信小程序首页的分类功能和搜索功能的实现思路及代码详解
2018/09/11 Javascript
解决layui中onchange失效以及form动态渲染失效的问题
2019/09/27 Javascript
Python中利用sorted()函数排序的简单教程
2015/04/27 Python
Python实现的桶排序算法示例
2017/11/29 Python
面向初学者的Python编辑器Mu
2018/10/08 Python
python学生管理系统开发
2019/01/30 Python
python 通过视频url获取视频的宽高方式
2019/12/10 Python
Python包,__init__.py功能与用法分析
2020/01/07 Python
Python基于Tensor FLow的图像处理操作详解
2020/01/15 Python
浅谈keras的深度模型训练过程及结果记录方式
2020/01/24 Python
在pycharm中为项目导入anacodna环境的操作方法
2020/02/12 Python
将labelme格式数据转化为标准的coco数据集格式方式
2020/02/17 Python
Python调用REST API接口的几种方式汇总
2020/10/19 Python
细说CSS3中box属性中的overflow-x属性和overflow-y属性值的效果
2014/07/21 HTML / CSS
印尼值得信赖的在线交易网站:Bukalapak
2019/03/11 全球购物
JRE、JDK、JVM之间的关系怎样
2012/05/16 面试题
教育课题研究自我鉴定范文
2013/12/28 职场文书
员工培训协议书
2014/09/15 职场文书
fastdfs+nginx集群搭建的实现
2021/03/31 Servers
Python数据分析入门之教你怎么搭建环境
2021/05/13 Python
Go 通过结构struct实现接口interface的问题
2021/10/05 Golang
zabbix自定义监控nginx状态实现过程
2021/11/01 Servers
使用Python获取字典键对应值的方法
2022/04/26 Python