scr*_*agz 42 javascript jquery events mutation-events
关于将未来的操作绑定到不存在的元素上存在很多问题,这些元素最终都以live/delegate回答.我想知道如何运行任意回调(例如,添加类或触发插件)到匹配选择器的所有现有元素以及与尚未创建的相同选择器匹配的所有未来元素.
似乎livequery插件的主要功能使其成为核心,但另一部分,附加任意回调在某种程度上丢失了.
另一个常见的答案是事件委派,但是如果一个人无法访问创建元素以触发事件的所有供应商代码,该怎么办?
这是一些现实世界的代码:
// with livequery
$('input[type=text], input[type=password], textarea, .basic_form .block select, .order_form .form_item select, .order_form .form_item input')
.livequery(function(){
$(this)
.focus(function(){
$(this).addClass('active');
})
.blur(function(){
$(this).removeClass('active');
})
.addClass('text');
});
// with live
$('input[type=text], input[type=password], textarea, .basic_form .block select, .order_form .form_item select, .order_form .form_item input')
.live('focus', function(){
$(this).addClass('active');
})
.live('blur', function(){
$(this).removeClass('active');
});
// now how to add the class to future elements?
// (or apply another plugin or whatever arbitrary non-event thing)
Run Code Online (Sandbox Code Playgroud)
一种方法是监视何时添加/删除新节点并重新触发我们的选择器.感谢@arnorhs,我们知道DOMNodeInserted事件,我会忽略跨浏览器的问题,希望那些小的IE补丁有一天能够上游到jQuery或知道jQuery DOM功能可以被包装.
但是,即使我们可以确保DOMNodeInserted触发了跨浏览器,但使用多个选择器绑定它也是荒谬的.可以随时创建数百个元素,并且可能会对每个元素进行数十个选择器调用.
是否可能更好地监控DOMNodeInserted/Deleted和/或挂钩到jQuery的DOM操作例程中,只设置一个"重新初始化"应该发生的标志?然后可能只有一个定时器,每隔x秒检查一次该标志,只在DOM实际发生变化时运行所有那些选择器/回调.
如果您以快速的速度添加/删除大量元素(如动画或____),那可能仍然非常糟糕.如果x很低,每x秒重新解析一次DOM,每隔x秒可能会过于激烈,如果x很高,界面会显得迟钝.
当它让我时,我会加一个赏金.我为最新颖的解决方案添加了赏金!
基本上我所了解的是一种更加面向方面的操作DOM的方法.可以允许将来创建新元素的一个,并且应该使用初始document.ready修改来创建它们.
JS最近能够做到这么多魔术,我希望它会很明显.
jAn*_*ndy 10
在我看来,DOM Level 3事件DOMNodeInserted有助于(仅针对节点触发)和DOMSubtreeModified帮助(实际上任何修改(例如属性更改)触发)是完成该任务的最佳方法.
当然,这些事件的最大缺点是,这个世界的互联网探索者不支持他们
(......好吧,IE9确实如此).
这个问题的另一个合理的解决方案是挂钩任何可以修改DOM的方法.但接下来我们要问,这里的范围是什么?
它是否足以处理来自特定库(如jQuery)的DOM修改方法?如果由于某种原因另一个库正在修改DOM甚至是本机方法会怎样?
如果它仅适用于jQuery,我们根本不需要.sub().我们可以用以下形式编写钩子:
HTML
<div id="test">Test DIV</div>
Run Code Online (Sandbox Code Playgroud)
JS
(function(_append, _appendTo, _after, _insertAfter, _before, _insertBefore) {
$.fn.append = function() {
this.trigger({
type: 'DOMChanged',
newnode: arguments[0]
});
return _append.apply(this, arguments);
};
$.fn.appendTo = function() {
this.trigger({
type: 'DOMChanged',
newnode: this
});
return _appendTo.apply(this, arguments);
};
$.fn.after = function() {
this.trigger({
type: 'DOMChanged',
newnode: arguments[0]
});
return _after.apply(this, arguments);
};
// and so forth
}($.fn.append, $.fn.appendTo, $.fn.after, $.fn.insertAfter, $.fn.before, $.fn.insertBefore));
$('#test').bind('DOMChanged', function(e) {
console.log('New node: ', e.newnode);
});
$('#test').after('<span>new span</span>');
$('#test').append('<p>new paragraph</p>');
$('<div>new div</div>').appendTo($('#test'));
Run Code Online (Sandbox Code Playgroud)
上面代码的实例可以在这里找到:http://www.jsfiddle.net/RRfTZ/1/
这当然需要完整的DOMmanip方法列表.我不确定你是否可以.appendChild()用这种方法覆盖原生方法.例如,.appendChild位于Element.prototype.appendChild,可能值得一试.
更新
我测试Element.prototype.appendChild了Chrome,Safari和Firefox中的覆盖等(官方最新版本).适用于Chrome和Safari,但不适用于Firefox!
可能还有其他方法可以解决这一要求.但是我想不出一个真正令人满意的方法,比如计算/观察节点的所有后代(需要一个interval或者timeoutseeek).
结论
DOM Level 3事件的混合,支持和挂钩的DOMmanip方法可能是您在这里可以做的最好的.
我正在阅读新版本的jQuery版本1.5,我立即想到了这个问题.
使用jQuery 1.5,您可以使用名为jQuery.sub()的东西创建自己的jQuery版本.
这样你就可以在jQuery中覆盖默认的.append(),insert(),. html(),..函数,并创建一个名为"mydomchange"的自定义事件 - 而不会影响所有其他脚本.
所以你可以做这样的事情(从带有小mod的.sub()文档中复制.):
var sub$ = jQuery.sub();
sub$.fn.insert = function() {
// New functionality: Trigger a domchange event
this.trigger("domchange");
// Be sure to call the original jQuery remove method
return jQuery.fn.insert.apply( this, arguments );
};
Run Code Online (Sandbox Code Playgroud)
您必须对所有dom操作方法执行此操作...
jQuery文档中的jQuery.sub():http: //api.jquery.com/jQuery.sub/
| 归档时间: |
|
| 查看次数: |
2300 次 |
| 最近记录: |