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 相关文章推荐
JS 日期验证正则附asp日期格式化函数
Sep 11 Javascript
jquery实现动静态条形统计图
Aug 17 Javascript
JavaScript中的时间处理小结
Feb 24 Javascript
jQuery CSS3自定义美化Checkbox实现代码
May 12 Javascript
jquery获取select,option所有的value和text的实例
Mar 06 Javascript
详谈angularjs中路由页面强制更新的问题
Apr 24 Javascript
windows下vue-cli及webpack搭建安装环境
Apr 25 Javascript
JS获取浏览器地址栏的多个参数值的任意值实例代码
Jul 24 Javascript
layui table设置某一行的字体颜色方法
Sep 05 Javascript
如何在vue中使用jointjs过程解析
May 29 Javascript
JavaScript中的Proxy对象
Nov 27 Javascript
JavaScript实现贪吃蛇游戏
Jun 16 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
substr()函数中文版
2006/10/09 PHP
php不写闭合标签的好处
2014/03/04 PHP
如何让搜索引擎抓取AJAX内容解决方案
2014/08/25 PHP
php类常量用法实例分析
2015/07/09 PHP
分享几种好用的PHP自定义加密函数(可逆/不可逆)
2020/09/15 PHP
javascript 清空form表单中某种元素的值
2009/12/26 Javascript
jQuery用unbind方法去掉hover事件及其他方法介绍
2013/03/18 Javascript
jQuery之选项卡的简单实现
2014/02/28 Javascript
搞定immutable.js详细说明
2016/05/02 Javascript
JavaScript中匿名函数的用法及优缺点详解
2016/06/01 Javascript
基于gulp合并压缩Seajs模块的方式说明
2016/06/14 Javascript
整理关于Bootstrap排版的慕课笔记
2017/03/29 Javascript
Angular4表单验证代码详解
2017/09/03 Javascript
微信小程序实现图片上传、删除和预览功能的方法
2017/12/18 Javascript
微信小程序中使用ECharts 异步加载数据实现图表功能
2018/07/13 Javascript
微信小程序wx:for循环的实例详解
2018/10/07 Javascript
vscode vue 文件模板的配置方法
2019/07/23 Javascript
javascript实现超好看的3D烟花特效
2020/01/01 Javascript
Python网络爬虫项目:内容提取器的定义
2016/10/25 Python
Python列表删除的三种方法代码分享
2017/10/31 Python
python sys,os,time模块的使用(包括时间格式的各种转换)
2018/04/27 Python
对numpy中的数组条件筛选功能详解
2018/07/02 Python
python代码 FTP备份交换机配置脚本实例解析
2019/08/01 Python
python3使用print打印带颜色的字符串代码实例
2019/08/22 Python
python中property属性的介绍及其应用详解
2019/08/29 Python
tensorflow 报错unitialized value的解决方法
2020/02/06 Python
python实现银行实战系统
2020/02/26 Python
万得城电器土耳其网站:欧洲第一大电子产品零售商
2016/10/07 全球购物
Contém1g官网:巴西彩妆品牌
2020/01/17 全球购物
网络工程专业毕业生推荐信
2013/10/28 职场文书
打造高效课堂实施方案
2014/03/22 职场文书
小班开学寄语
2014/04/04 职场文书
社会发展项目建议书
2014/08/25 职场文书
迟到检讨书范文
2015/01/27 职场文书
护士求职自荐信
2015/03/25 职场文书
Python anaconda安装库命令详解
2021/10/16 Python