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 相关文章推荐
jquery 之 $().hover(func1, funct2)使用方法
Jun 14 Javascript
js实现快速分享功能(你的文章分享工具)
Jun 25 Javascript
JS实现滑动菜单效果代码(包括Tab,选项卡,横向等效果)
Sep 24 Javascript
Jquery轮播效果实现过程解析
Mar 30 Javascript
jQuery绑定事件on()与弹窗的简要概述
Apr 27 Javascript
利用Query+bootstrap和js两种方式实现日期选择器
Jan 10 Javascript
微信小程序 PHP后端form表单提交实例详解
Jan 12 Javascript
bootstrap响应式导航条模板使用详解(含下拉菜单,弹出框)
Nov 17 Javascript
vue 动态改变静态图片以及请求网络图片的实现方法
Feb 07 Javascript
JavaScript简单实现关键字文本搜索高亮显示功能示例
Jul 25 Javascript
jQuery中ajax请求后台返回json数据并渲染HTML的方法
Aug 08 jQuery
Vue数据双向绑定原理实例解析
May 15 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
将兴奋、喜悦和坎加斯带到戴安娜:亚马逊公主
2020/03/03 欧美动漫
百度工程师讲PHP函数的实现原理及性能分析(一)
2015/05/13 PHP
关于PHP定时发送服务的解决办法
2017/04/23 PHP
Gambit vs ForZe BO3 第一场 2.13
2021/03/10 DOTA
Javascript 日期处理之时区问题
2009/10/08 Javascript
服务器端的JavaScript脚本 Node.js 使用入门
2012/03/07 Javascript
利用webqq协议使用python登录qq发消息源码参考
2013/04/08 Javascript
QQ登录背景闪动效果附效果演示源码下载
2015/09/22 Javascript
jQuery 1.9.1源码分析系列(十)事件系统之主动触发事件和模拟冒泡处理
2015/11/24 Javascript
一个简单的JavaScript Map实例(分享)
2016/08/03 Javascript
基于JavaScript实现本地图片预览
2017/02/08 Javascript
探索Vue高阶组件的使用
2018/01/08 Javascript
解决Echarts 显示隐藏后宽度高度变小的问题
2020/07/19 Javascript
浅谈JavaScript中的“!!”作用
2020/08/03 Javascript
Python监控主机是否存活并以邮件报警
2015/09/22 Python
Python中应该使用%还是format来格式化字符串
2018/09/25 Python
python bmp转换为jpg 并删除原图的方法
2018/10/25 Python
漂亮的Django Markdown富文本app插件的实现
2019/01/02 Python
Python3.5装饰器典型案例分析
2019/04/30 Python
python求最大值最小值方法总结
2019/06/25 Python
Python实现Selenium自动化Page模式
2019/07/14 Python
python pandas cumsum求累计次数的用法
2019/07/29 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
2019/12/04 Python
python使用信号量动态更新配置文件的操作
2020/04/01 Python
使用before和:after伪类制作css3圆形按钮
2014/04/08 HTML / CSS
canvas环形倒计时组件的示例代码
2018/06/14 HTML / CSS
城市观光通行证:The Sightseeing Pass
2018/04/28 全球购物
办公室前台岗位职责
2014/01/04 职场文书
小学标准化建设汇报材料
2014/08/16 职场文书
学习教师敬业奉献模范事迹材料思想汇报
2014/09/19 职场文书
2014广电局实施党的群众路线教育实践活动方案思想汇报
2014/09/22 职场文书
会计实训报告范文
2014/11/04 职场文书
北京故宫导游词
2015/01/31 职场文书
明星邀请函
2015/02/02 职场文书
2016新年年会主持词
2015/07/06 职场文书
军训心得体会范文(2016最新篇)
2016/01/11 职场文书