情景如下 服务端响应后渲染一个 js.erb 文件 内容如下:
$('#msg').append("<%= escape_javascript(render partial: 'share/messages', locals: {message: "ok" } )%>")
share/messages 的内容如下:
<div class="notice" id="failed">
<%= message %>
<div></div>
</div>
页面上有段 js 是控制 share/messages 内容的
//点击差号关闭notice栏
$(".notice>div").click(function(){
$(".notice").fadeOut("fast");
});
不响应异步请求前 js 是好用的,但是响应并渲染 js.erb 之后,这段 js 失效了,我在浏览器的 console 里面手动执行这段 js 后,才有效,是我遗漏了 什么东西?
#1 楼 @guyanbiao 奥奥 我也考虑过是顺序问题,如果放到 callback 里面 用 js.erb 这种怎么写?还是必须用服务端返回 json,在客户端的 callback 里面实现?
如一楼所说,适应为你绑定事件对时候,“.notice>div”这个 dom 还没有出现在页面,所以 $(".notice>div") 返回为 [],事件就没有绑定。
解决方法两种:
如一楼,把时间绑定写到 js.erb 中,的 append 操作时候
$('#msg').append("<%= escape_javascript(render partial: 'share/messages', locals: {message: "ok" } )%>")
$(".notice>div").click(function(){
$(".notice").fadeOut("fast");
});
如下,通过 "#msg" 这个父 DOM 来进行事件绑定。原理参照 http://api.jquery.com/on/
//点击差号关闭notice栏
$("#msg").on("click", ".notice>div", function(){
$(this).closest(".notice").fadeOut("fast");
});
个人倾向于第二种,click 事件只需绑定一次。而第一种则需要每 append 一次消息,都要绑定一次。
$(document).on('click', '.notice-close', function(e) {
});
#9 楼 @TsingHan 如果 div 已经插入 dom tree,那 js 是肯定能找到的。你这里没有触发事件是因为新进来的 dom 没有绑定回调函数。
WHY?
$('.notice>div') 这段代码是找出所有 .notice 下第一层 div 的元素
然后,用 click 函数绑定事件回调。这个动作会将事件附加到 .notice>div 这个对象上,也就是说,$(',notice>div').click 只会对执行代码时页面存在的元素生效。
当你动态生成新对象时,代码已经执行了,所以这个新对象没有绑定回调,也就无法运行了。
=================
而用 on 函数委托事件是利用浏览器的冒泡机制
在页面里,用户每点击一次,浏览器就会提升事件到 document 对象。换句话说,on 函数并不是找到 div,而是 div 元素在对祖先节点逐个呼喊:“老子被人点啦!”,直到有人对他作出回应,也就是用 on 函数捕获了事件。