最近同事问到一个问题,一个前端页面在IOS端真机测试下出现一个比较诡异的问题,若是没有遇到过估计也是束手无策。今天特此记录一下,或许能帮到后面遇到这个问题的朋友少绕一些弯路。这是关于JQuery 中的 delegate 和 on 给动态元素绑定事件触发不了的问题。文章如下只用 delegate 举例。css
首先咱们来了解一下 Delegate 的做用。一句话带过:“给动态添加的元素绑定事件”html
看图:前端
下面九个测试按钮是经过点击上面的 “添加测试按钮” 按钮添加的。这就是动态添加元素的概念。接下来需求为每一个添加的测试按钮都有统一的处理事件。这边做为测试,当点击时输出 “你点击了+按钮名称” 信息。 按平时绑定事件的方式,.click() 或者 on('click') 等等这些方式。代码以下jquery
$(function(){ //“添加测试按钮” 按钮点击事件,测试按钮 class 为 new-btn $("#add-btn").click(function(){ var test_btn_count = $('#btn-line button').size(); var new_btn_html = '<div class="new-btn btn">测试按钮' + (test_btn_count + 1) +'</div>'; $('#btn-line').append(new_btn_html); }); //用普通的click 绑定事件。很遗憾,没任何反应 $('.new-btn').click(function(){ console.log('你点击了按钮:'+$(this).text()); }) })
效果如图:web
接下来咱们将普通的绑定事件换成 delegate ,代码以下:canvas
//btn-line 为存放 new-btn 的容器 $('.btn-line').delegate('.new-btn','click',function(){ console.log('你点击了按钮:'+$(this).text()); })
delegate 效果ruby
至此,Delegate 解决了动态元素的事件绑定问题。app
上面好像已经实现了咱们要的需求,但事实证实真正的坑还在后面。如今 Chrome 下面的 IOS模拟器下面所有正常。可是当项目正在跑在真机上,点击测试按钮又失去了反应。为了在手机上看到效果,咱们先把 console.log 换成 alertide
$('.btn-line').delegate('.new-btn','click',function(){ alert('你点击了按钮:'+$(this).text()); })
结果是界面直接懵圈了。post
点击没有任何的 alert 信息
针对这个问题开始了搜索之旅,功夫不负有心人(其实不难搜到)。一切诡异的问题后面都会有一个神奇的解决方案。
给动态添加的 new-btn 添加 css cursor属性
.new-btn{ cursor: none; }
神奇地好了
网友对此的回答以下:
其实苹果对于性能的要求是近乎苛刻的,这样的特性应该是苹果为了节省性能开销而产生的一个bug。若是没有可点的特性的元素系统默认不会给它响应事件。而咱们添加的这个 cursor 属性就是让元素看起来是能够点击的,也就向操做系统指明这个元素是须要响应事件的。
也就是说,想要一劳永逸,给body 添加 cursor:pointer 样式属性。或者按照网友提供的方法,经过js判断当前是否为苹果设备,若是是则加上。
代码以下:
if(/ip(hone|od)|ipad/i.test(navigator.userAgent)){ $("body").css("cursor","pointer"); }
其实我到时以为css代码更干脆
body{ cursor:none;
/*cursor:pointer;*/
}
//或者 *{ cursor:pointer; }
可是直接给body或者是给 * 添加这个属性都违背了苹果节约性能开销的初衷,最好的方式仍是直接给须要响应事件的元素添加 cursor 属性.
.yourElementClass{
cursor:pointer;
}
限于笔者技术,文章观点不免有不当之处,但愿发现问题的朋友帮忙指正,笔者将会及时更新。也请转载的朋友注明文章出处并附上原文连接,以便读者能及时获取到文章更新后的内容,以避免误导读者。笔者力求避免写些晦涩难懂的文章(虽然也有人说这样显得高逼格,专业),尽可能使用简单的用词和例子来帮助理解。若是表达上有好的建议的话也但愿朋友们在评论处指出。
本文为做者原创,转载请注明出处! Cboyce