【问题标题】:I need a new way to detect if there has been a change to an elements HTML我需要一种新方法来检测元素 HTML 是否发生了变化
【发布时间】:2012-06-13 23:24:50
【问题描述】:

现在我正试图找到一种方法来检测元素 HTML 何时发生变化。

我目前正在尝试:

var a, b;
setInterval(function() {
    a = $('#chat').text();
}, 150);
setInterval(function() {
    b = $('#chat').text();
    if (a !== b) {
        alert("There has been a new message.");
    }
}, 200);​

我所做的是每 150 毫秒检查一次 #chat 的 HTML,然后每 200 秒再次检查一次 HTML,然后检查变量 a 是否不等于变量 b 将来我会所以有一些东西,但现在我只是提醒一些东西。

你可以在这里看到它:http://jsfiddle.net/MT47W/

显然这种方法行不通,而且根本不是很准确。 有没有更好/不同的做法/实现这一目标?

感谢您的帮助,大约一个星期以来,我一直在试图弄清楚如何更好地做到这一点,但我找不到解决这个问题的方法,我希望我在右边发布了这个问题地点,并且在正确的时间。

【问题讨论】:

    标签: javascript jquery setinterval detect


    【解决方案1】:

    使用var 存储元素的当前text,然后在setInverval 中检查它,并在检查后更新var 以存储当前text

    var a = $('#chat').text();
    setInterval(function() {
        if (a !== $('#chat').text()) { //checks the stored text against the current
            alert("There has been a new message."); //do your stuff
        }
        a = $('#chat').text(); //updates the global var to store the current text
    }, 150); //define your interval time, every 0.15 seconds in this case
    

    Fiddle

    您也可以将值存储在元素的.data() 中以避免使用全局变量。

    使用.data()的示例:

    $('#chat').data('curr_text', $('#chat').text());
    setInterval(function() {
        if ($('#chat').data('curr_text') !== $('#chat').text()) {
            alert("There has been a new message.");
        }
         $('#chat').data('curr_text', $('#chat').text());
    }, 150);
    

    Fiddle

    另一种方法,为了节省客户的内存,您可以只存储您的#chat 元素具有的子divs 的数量:

    $('#chat').data('n_msgs', $('#chat').children().length);
    setInterval(function() {
        if ($('#chat').data('n_msgs') !== $('#chat').children().length) {
            alert("There has been a new message.");
        }
         $('#chat').data('n_msgs', $('#chat').children().length);
    }, 150);
    

    Fiddle


    编辑:这是我最后的补充,DOM mutation event listener
    $('#chat').on('DOMNodeInserted', function() {
        alert("There has been a new message.");
    });
    

    Fiddle(未在 IE

    注意: 如 cmets 中所述,即使仍然支持突变事件,但由于性能损失和不同浏览器之间的一些不兼容,它们仍被归类为 deprecated by W3C,因此建议使用上述解决方案之一,仅在没有其他方法时才使用 DOM Mutation 事件。

    【讨论】:

    • 我可能弄错了,但我很确定监听 DOM 事件并没有得到很好的支持,并且完全从最新规范中删除。
    • @VahurRoosimaa,我可能弄错了,但 jQuery 主要用于 DOM 事件侦听事件委托,我发现它最近被广泛用于答案。现在,如果它带来任何兼容性问题,任何旧版本也可以使用。 =] 或者你的意思是,DOM 突变事件?
    • 哇,非常感谢。我从未听说过: DOMNodeInserted 并且不确定是否会像 Vahur 所说的那样得到很好的支持,所以我认为不应该使用第二种方法。但是感谢所有这些方式。但我也确实想过在#chat 中使用仅获取孩子长度的数据。好吧,我每天都学到新东西! :)
    • @Shawn31313 相同。 =]如果有人有更多关于被弃用的DOM突变事件的信息,请随时分享,我会在答案中进行编辑。到目前为止,我发现的只是突变事件会降低性能,我将添加一个注释,避免在答案中使用这些事件。
    • @VahurRoosimaa 是的,你是对的,我在 w3c 上找到了一些资料并添加了一条注释,以避免使用 DOM mutation 事件,除非绝对必要。
    【解决方案2】:

    只检查最后一次聊天会提高效率,也可以做你想做的事。它不起作用的唯一方法是如果同一个人两次发送相同的消息 - 这很可能不会发生。

    我希望这会奏效:

     var lastMessage = $('#chat .body').last().text();
        function checkMessages(){
            var newLastMessage = $('#chat .body').last().text();
            if(lastMessage !== newLastMessage && $('#chat .body').last().length > 0){
                 //message has changed
                alert("There has been a new message.");
                lastMessage = $('#chat .body').last().text();
            }
            setTimeout(function(){checkMessages();},1000);
        }
        checkMessages();
    

    Js Fiddle

    【讨论】:

    • 如果同一个用户两次发布相同的消息怎么办?您的函数不会针对垃圾邮件发送者触发:P
    • 好点。但是,我相当确定用户不会希望收到来自垃圾邮件发送者的持续通知。此外,这并不重要,因为“新消息”基本上是相同的消息。 :D
    • 哪些浏览器不支持 setInterval?
    • 抱歉,过去我在自己的一个脚本中遇到了与 setInterval 的浏览器兼容性问题。但是,根据developer.mozilla.org/en/DOM/window.setInterval,它在IE 4 及更高版本中受支持。我将删除那部分....
    【解决方案3】:

    使用 crc32 或 md5 哈希检查数据是否已更改。只需获取要检查的 div 的 html 内容,使用 crc32 或 md5 将其哈希为字符串,您将获得一个表示该内容的字符串。使用隐藏的时间戳等来确保一个用户的多条消息获得不同的哈希值。如果您在 setInterval 回调中执行此操作,您应该会很好。

    【讨论】:

      【解决方案4】:

      虽然不强烈推荐,但也可以使用Paul Irish's Duck punching 方法绑定到jQuery 的追加功能 - 如果您确定append 功能是内容的方式添加(demo):

      (function($) {
          // store original reference to the method
          var _old = $.fn.append;
          $.fn.append = function(arg) {
              // append as usual
              _old.apply(this, arguments);
      
              // do your own checking here
              // "this" is a jQuery object
              if (this[0].id === "chat") {
                  alert('there is a new message!');
              }
              return this;
          };
      
      })(jQuery);
      

      使用这种方法,不需要定时循环。

      【讨论】:

        猜你喜欢
        • 2016-04-12
        • 2013-05-29
        • 1970-01-01
        • 2012-08-18
        • 1970-01-01
        • 1970-01-01
        • 2017-04-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多