2012-07-15 38 views
38

我需要注意特定DOM元素的任何子元素的屬性更改。到目前爲止,我一直在使用mutation events注意DOM的變化,優雅的方式

問題是 - 他們是越野車:例如根據Chromium,DOMAttrModified沒有被解僱,但是DOMSubtreeModified是。問題很容易解決:因爲根據規範,如果其他任何事件被觸發,DOMSubtreeModified會被觸發,所以我只聽到DOMSubtreeModified

無論如何,在最近的版本中,如果屬性已被修改,則Chromium會停止發射任何東西。

然而,新的Mutation Observer API完美無瑕。直到現在,我只需要在任何特定元素的子樹的任何變化時觸發回調 - 僅僅因爲沒有別的東西應該改變 - 所以我通過使用突變事件來解決我的問題&突變觀察者(當可用時)在同一段代碼中。

但是,現在我需要對事件進行更強大的過濾(例如,在新節點上,在已刪除的節點上) - 所以有庫,可能是jQuery插件,這將允許我優雅地使用這些API的均爲 - MutationObserver(如果可用)和突變事件作爲回退,並具有針對特定事件類型(例如添加元素,更改屬性)進行過濾的功能。

E.g.

$("#test").watch({onNewElement: 1}, function(newElement){}) 
$("#test").watch({onNewAttribute: 1}, function(modifiedElement) {}) 

或者沒有jQuery的

watchChanges("#test", {onNewElement: 1}, function(newElement){}) 
watchChanges("#test", {onNewAttribute: 1}, function(modifiedElement){}) 
+0

一些搜索發現這一點,但它僅支持新的API:http://code.google.com/p/mutation-summary/ 。我也發現,這似乎是你要求的簡單版本:http://stackoverflow.com/questions/10868104/can-you-have-a-javascript-hook-trigger-after-a- dom-elements-style-object-change – thirtydot 2012-07-15 11:56:13

+0

我也發現了突變總結,但它不支持突變事件作爲後備。 你發佈的線程的第一個答案基本上是我在我的代碼中觀察屬性更改。 同樣的原理,可以構建一個庫,允許使用突變觀察者和(作爲後備)事件觀察特定的DOM事件。那是我需要的。 – Ivo 2012-07-15 12:00:57

+2

+1:我真的挖掘'最佳實踐'的問題。 – 2012-07-21 23:50:57

回答

2

將這項工作?

http://darcyclarke.me/development/detect-attribute-changes-with-jquery/

$.fn.watch = function(props, callback, timeout){ 
    if(!timeout) 
     timeout = 10; 
    return this.each(function(){ 
     var el  = $(this), 
      func = function(){ __check.call(this, el) }, 
      data = { props: props.split(","), 
         func: callback, 
         vals: [] }; 
     $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); }); 
     el.data(data); 
     if (typeof (this.onpropertychange) == "object"){ 
      el.bind("propertychange", callback); 
     } else if ($.browser.mozilla){ 
      el.bind("DOMAttrModified", callback); 
     } else { 
      setInterval(func, timeout); 
     } 
    }); 
    function __check(el) { 
     var data = el.data(), 
      changed = false, 
      temp = ""; 
     for(var i=0;i < data.props.length; i++) { 
      temp = el.css(data.props[i]); 
      if(data.vals[i] != temp){ 
       data.vals[i] = temp; 
       changed = true; 
       break; 
      } 
     } 
     if(changed && data.func) { 
      data.func.call(el, data); 
     } 
    } 
} 
+0

我看到它,但它只是用於屬性。另外,即使瀏覽器可能支持DOMAttrModified,它也會回退到setInterval。 – Ivo 2012-07-21 23:53:50

+0

@Ivo對。這是一個想法 - 你是否在控制所有這些變化發生的變化?你有沒有考慮覆蓋jQuery的操作方法來觸發一個更改/附加/刪除事件(但假設所有更改都是通過jquery進行的)。我知道這是很多工作,而不是你正在尋找的東西,但完成工作。 – 2012-07-22 00:54:08

+1

我已經完成了很久以前的工作 - 我使用突變事件和觀察者來監視屬性,並且我僅使用事件來監視DOM上新增加的內容 - 而且由於我本人的控制力不夠,觀察通過contenteditable/WYSIHTML5編輯器所做的更改。但這一切都適用於我計劃支持的瀏覽器。 這更像是一個「最佳方法」問題。 和猴子補丁jQuery似乎是一個壞主意。猴子修補DOM API可能更合適,但我仍然不確定。 – Ivo 2012-07-22 10:43:36

2

對於使用jQuery高效DOM監控,你可能需要看看jQuery Behavior Plugin(聲明:我是作者),它採用的Live Query一個優化版本。我現在在幾種產品中使用它3年,沒有任何問題。

編輯:監聽屬性變化將這樣的工作:

$.behavior({ 
    'div:first': { 
     'changeAttr': function (event, data) { 
      console.log('Attribute "' + data.attribute + '" changed from "' + data.from + '" to "' + data.to + '"'); 
     } 
    } 
}); 

$('div:first').attr('foo', 'bar');