检测DOM元素顺序的变化

时间:2016-11-02 15:13:40

标签: javascript jquery dom

我有以下代码:

<div>
  <span>Random text</span> 
  <span style="color: red">Random text</span>
</div>

并且,使用代码,我有50%的机会更改div中元素的顺序。

$(document).ready(function() {
  var initial = $("div"); //This might not be ok

  if (new Date() % 2) //50% chance to randomize order 
    randomizeOrder();

  var after = $("div"); //Also this might not be ok
  //Detect if the order of spans changed
  if (after != initial) //Definitely won't work
    console.log("Order changed");
})

function randomizeOrder() {
  var lastElement = $("div span").last();
  $(lastElement).insertBefore($("div span").first());
}

此示例过于简单。订购是由用户使用第三方库完成的,该库不会告诉我订单是否实际发生变化,只需告诉我它何时开始&amp;结束。

如何检测DOM元素的顺序是否实际发生了变化?我在其中的信息不能使用,因为它可以完全相同,如示例中所示。

Fiddle

2 个答案:

答案 0 :(得分:15)

如果您想检查DOM中的更改,可以使用MutationObserver

$(document).ready(function() {
  var initial = $("div"); //This might not be ok

  if (new Date() % 2) {
    randomizeOrder();
  }
  
});

function randomizeOrder() {
  var lastElement = $("div span").last();
  $(lastElement).insertBefore($("div span").first());
}

var target = document.getElementById('id1');

// create an observer instance
var observer = new MutationObserver(function(mutations) {
  var changed = false;
  mutations.forEach(function(mutation) {
    // You can check the actual changes here
  });
  console.log('Dom Changed');
});

// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true };

// pass in the target node, as well as the observer options
observer.observe(target, config);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="id1">
  <span>Random text</span> 
  <span style="color: red">Random text</span>
</div>

MutationObserver使您能够检查特定元素中的DOM更改,而无需更改DOM的代码。

答案 1 :(得分:1)

我终于想出了解决方案,它完成了我想要的和我最初想到的方式,但不知道如何实现它:

  var before = Array.prototype.slice.call($("div")[0].children).map(x => x);

  if (new Date() % 2) //50% chance to randomize order 
    randomizeOrder();

  var after = Array.prototype.slice.call($("div")[0].children).map(x => x);

  //Detect if the order of spans changed
  var hasChanged;
  after.forEach((el, i) => {
    if (el != before[i]) {
      hasChanged = true;
    }
  })
  hasChanged && console.log("Something's changed");

秘诀是在排序之前和之后基本上保持对子节点的引用,然后比较它们,但不是对element.children的直接引用,因为它与DOM一起更新,而是创建新的数组,并且按照现在的顺序在他们里面有孩子。

Updated fiddle