你的位置:首页 > Java教程

[Java教程]关于 Touchjs 手势识别事件库 this 关键字与选择器不对称情况


Touchjs 版本 v0.2.14

废话不多,直接看代码,一个拖动实例

<div id="touch-drag"></div><script type="text/javascript">var dx, dy;touch.on('#touch-drag', 'drag', function(ev){  dx = dx || 0;  dy = dy || 0;  var offx = dx + ev.x + "px";  var offy = dy + ev.y + "px";  this.style.webkitTransform = "translate3d(" + offx + "," + offy + ",0)";  console.log(this); //-> <div id="touch-drag"></div>});touch.on('#target', 'dragend', function(ev){  dx += ev.x;  dy += ev.y;});</script>

拖动正常,demo 完成,自信满满的去交工,30分钟后。。。 什么,报错? 怎么可能,我来看看 ↓

 

<div id="touch-drag">  <h2>小火箭</h2>  <img src="..." />  <span>∧∪∧</span></div><script type="text/javascript">var dx, dy;touch.on('#touch-drag', 'drag', function(ev){  dx = dx || 0;  dy = dy || 0;  var offx = dx + ev.x + "px";  var offy = dy + ev.y + "px";  this.style.webkitTransform = "translate3d(" + offx + "," + offy + ",0)";  console.log(this); //-> <img src="..." />  console.log(this); //-> <h2>小火箭</h2>  console.log(this); //-> <span>∧∪∧</span>});touch.on('#target', 'dragend', function(ev){  dx += ev.x;  dy += ev.y;});</script>

xxxx ,怎么加了两个子节点就拖得乱七八糟,this 怎么不是选择器 "#touch-drag" ,杯具。。。

尝试方法一:console.log(ev); //-> 找找看 #touch-drag,失败
尝试方法二:应急处理,递归回 #touch-drag

var _this = (function(){ var stack_max = 100; //防止堆栈溢出 var f = function(target){   var id = target.getAttribute("id");   if(!!stack_max--) return false;   if( !!id && id ==="#touch-drag" ) return target;   return f( target.parentNode ); }; return f(arguments[0]) || console.error("Did not find the "#touch-drag" node");})(this);

 

看看官方的 API 说明

事件代理

touch.on( delegateElement, types, selector, callback );

功能描述:

事件代理方法。

参数描述:

参数类型描述
delegateElementelement或string事件代理元素或选择器
typesstring手势事件的类型, 可接受多个事件以空格分开;支持原生事件的透传。目前支持的具体事件类型,详见《手势事件类型》。
selectorstring代理子元素选择器,
callbackfunction事件处理函数,如需了解手势库支持的新属性,详见《事件对象》

经过测试,即使添加了第三个参数 selector ,this 依然不是我们想要的,那只能看看源码了。

 

仔细想想,touchjs 绑定很像 jQuery 的事件委托,this -> e.target,找找 touchjs 源码

var E = {};  return E.on = E.bind = E.live = B,  E.off = E.unbind = E.die = C,  E.config = d,  E.trigger = D,  E

 

源码最后一块,原来绑定事件的方法就是一个呀,为了支持常用习惯,多写了几个同名的,再找找

 

bind: function(a, c, d) {  a.listeners = a.listeners || {},  a.listeners[c] ? a.listeners[c].push(d) : a.listeners[c] = [d];  var e = function(a) {    b.env.ios7 && b.forceReflow(),    a.originEvent = a;    for (var c in a.detail)"type" !== c && (a[c] = a.detail[c]);    a.startRotate = function() {      t = !0    };    var e = d.call(/*a.target*/this, a);      "undefined" == typeof e || e || (a.stopPropagation(), a.preventDefault())  };  d.proxy = d.proxy || {},  d.proxy[c] ? d.proxy[c].push(this.proxyid++) : d.proxy[c] = [this.proxyid++],  this.proxies.push(e),  a.addEventListener && a.addEventListener(c, e, !1)}

终于找到了, 看代码

var e = d.call(/*a.target*/this, a);

经过测试,OK

注:以上纯属个人看法,如有不当之处,请多多指教