【问题标题】:chrome MutationObserver for new paragraph textchrome MutationObserver 用于新段落文本
【发布时间】:2015-09-02 13:10:56
【问题描述】:

我还没有真正理解如何使用mutationObserver,但我目前所拥有的似乎有点正确......每次新的p标签出现在代码中时我都想做一个动作......这里是到目前为止我的代码:

var target = $('p');
var observer = new WebKitMutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        chrome.storage.sync.get({ getInjection: true }, function(getInject) {
        var getInjectionState = getInject.getInjection;
        if(getInjectionState == true) {
                arrayOfP = $("p").text();
                chrome.runtime.sendMessage(arrayOfP, manageResponse);
            }
        });
    });    
});
observer.observe(target[0], { attributes: true, childList: true, characterData: true });

此代码位于 chrome 扩展程序的内容脚本中。为什么它不起作用?任何帮助,将不胜感激。谢谢!

【问题讨论】:

标签: javascript jquery google-chrome google-chrome-extension google-chrome-app


【解决方案1】:
  1. observer.observe 应该观察添加了新的p 元素或document.body 的父/容器元素。

    • observer.observe($('.some-container-selector')[0], .....
    • observer.observe(document.body, .....
  2. 在回调中你应该检查添加的节点是否真的是p

    mutations.forEach(function(mutation) {
      Array.prototype.forEach.call(mutation.addedNodes, function(node) {
        if (node.nodeType != 1) return; // only process Node.ELEMENT_NODE
        if (node.localName != 'p') { // not P but might be DIV with P inside
          node = node.querySelector('p');
          if (!node) return;
        }
        // now we have our P node
        console.log("Got P!", node);
      });
    });
    


作为替代方案,这里有一个我重用了几年的函数,它有一个更丑但更快的 for 循环:

function setMutationHandler(baseNode, selector, cb) {
  new MutationObserver(function(mutations) {
    for (var i=0, ml=mutations.length, m; (i<ml) && (m=mutations[i]); i++)
      for (var j=0, nodes=m.addedNodes, nl=nodes.length, n; (j<nl) && (n=nodes[j]); j++)
        if (n.nodeType == 1) 
          if ((n = n.matches(selector) ? [n] : n.querySelectorAll(selector)) && n.length)
            if (!cb.call(this, [].slice.call(n)))
              return;
  }).observe(baseNode, {subtree:true, childList:true}); 
}

用法(这里的回调将只接收p.some-container-class 的元素):

setMutationHandler(document, '.some-container-class p', function(nodes) {
  nodes.forEach(function(node) {
    console.log("Got node", node);
    // do something
  });
  //this.disconnect(); // disconnect the observer, useful for one-time jobs
  //return true; // continue enumerating current batch of mutations
});

与 setMutationHandler 的循环相比,最后一个 for 循环很少发生,因此它可以替换为更简洁的 [].forEach.call(nodes, ...Array.prototype.forEach.call(nodes, .... 或带有 .each 的 jQuery 包装器。

附言对于 Chrome pre-34,这在脚本开头的某个地方是必需的:

if (!Element.prototype.matches)
    Element.prototype.matches = Element.prototype.webkitMatchesSelector;

【讨论】:

  • 感谢您的优质帖子!我对 javascript 还是很陌生,我将如何在我的代码中实现 thi?我需要第二个项目符号和用法吗?还是我遗漏了什么?
  • @Katie,做 #1 和 #2,忽略 #3。
  • 我不想问这个问题,但我似乎收到了错误Uncaught TypeError: mutation.addedNodes.forEach is not a function.. 这是我在JSFiddle 上的实现。知道为什么会这样吗?
  • 啊,我一直在使用我的自定义处理程序,忘记了 addedNodes 不是数组,请参阅更新的代码。
猜你喜欢
  • 2013-06-29
  • 2012-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 2010-11-05
  • 2011-04-13
  • 2012-09-16
相关资源
最近更新 更多