chrome 新段落文本的 MutationObserver
chrome MutationObserver for new paragraph text
我还没有真正理解如何使用 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 扩展的内容脚本中。为什么它不起作用?任何帮助,将不胜感激。谢谢!
observer.observe
应该观察添加了新 p
元素的 parent/container 元素或 document.body
.
observer.observe($('.some-container-selector')[0], .....
observer.observe(document.body, .....
在回调中你应该检查添加的节点是否实际上是 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});
}
用法(这里的回调将仅接收 .some-container-class
下的 p
个元素):
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, ....
或 jQuery 包装器替换为 .each
.
P.P.S。对于 Chrome pre-34,这需要在脚本开头的某处:
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.webkitMatchesSelector;
我还没有真正理解如何使用 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 扩展的内容脚本中。为什么它不起作用?任何帮助,将不胜感激。谢谢!
observer.observe
应该观察添加了新p
元素的 parent/container 元素或document.body
.observer.observe($('.some-container-selector')[0], .....
observer.observe(document.body, .....
在回调中你应该检查添加的节点是否实际上是
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});
}
用法(这里的回调将仅接收 .some-container-class
下的 p
个元素):
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, ....
或 jQuery 包装器替换为 .each
.
P.P.S。对于 Chrome pre-34,这需要在脚本开头的某处:
if (!Element.prototype.matches)
Element.prototype.matches = Element.prototype.webkitMatchesSelector;