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 Undefined,Null类型和NaN值区别
Oct 22 Javascript
javascript 必知必会之closure
Sep 21 Javascript
javascript 全等号运算符使用说明
May 31 Javascript
JavaScript判断是否为数组的3种方法及效率比较
Apr 01 Javascript
javascript常见数字进制转换实例分析
Apr 21 Javascript
jQuery简单实现彩色云标签效果示例
Aug 01 Javascript
Vue.js基础知识小结
Jan 13 Javascript
javascript实现电脑和手机版样式切换
Nov 10 Javascript
JS关闭子窗口并且刷新上一个窗口的实现示例
Mar 10 Javascript
Vue中el-form标签中的自定义el-select下拉框标签功能
Apr 20 Javascript
详解vue高级特性
Jun 09 Javascript
express异步函数异常捕获示例详解
Nov 30 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游戏编程25个脚本代码
2011/02/08 PHP
php批量删除操作(数据访问)
2017/05/23 PHP
ThinkPHP 5.x远程命令执行漏洞复现
2019/09/23 PHP
php实现微信和支付宝支付的示例代码
2020/08/11 PHP
原生javascript实现无间缝滚动示例
2014/01/28 Javascript
JS+CSS模拟可以无刷新显示内容的留言板实例
2015/03/03 Javascript
jQuery Validate初步体验(一)
2015/12/12 Javascript
jQuery实现产品对比功能附源码下载
2016/08/09 Javascript
JQueryEasyUI之DataGrid数据显示
2016/11/23 Javascript
学习vue.js条件渲染
2016/12/03 Javascript
JS实现的样式切换功能tableCSS实例
2016/12/30 Javascript
快速实现jQuery多级菜单效果
2017/02/01 Javascript
JavaScript实现的鼠标响应颜色渐变效果完整实例
2017/02/18 Javascript
nodejs连接mysql数据库简单封装示例-mysql模块
2017/04/10 NodeJs
JS中关于正则的巧妙操作
2017/08/31 Javascript
图片加载完成再执行事件的实例
2017/11/16 Javascript
使用vue实现HTML页面生成图片的方法
2020/03/12 Javascript
基于Python的身份证号码自动生成程序
2014/08/15 Python
举例讲解Python中is和id的用法
2015/04/03 Python
基于python 二维数组及画图的实例详解
2018/04/03 Python
python字符串常用方法
2018/06/14 Python
django 框架实现的用户注册、登录、退出功能示例
2019/11/28 Python
Python3列表List入门知识附实例
2020/02/09 Python
python 利用toapi库自动生成api
2020/10/19 Python
英国儿童图书网站:Scholastic
2017/03/26 全球购物
美国折扣网站:jClub
2017/08/07 全球购物
阿迪达斯荷兰官方网站:adidas荷兰
2018/03/16 全球购物
Hoka One One法国官网:美国专业跑鞋品牌
2018/12/29 全球购物
新西兰便宜隐形眼镜购买网站:QUICKLENS New Zealand
2019/03/02 全球购物
德国价格合理的品牌商品购物网站:averdo
2019/03/21 全球购物
讲党性心得体会
2014/09/03 职场文书
教师先进事迹材料
2014/12/16 职场文书
企业安全隐患排查治理制度
2015/08/05 职场文书
2015质检员个人年终工作总结
2015/10/23 职场文书
如何在pycharm中快捷安装pip命令(如pygame)
2021/05/31 Python
Python使用socket去实现TCP客户端和TCP服务端
2022/04/12 Python