我需要在文档加载时创建带有“nav”类的元素时收到通知。谷歌搜索我发现MutationObservers并认为他们会很完美,但我似乎无法让它工作。
// ==UserScript==
// @name ii-shortcuts
// @namespace https://github.com/RedHatter
// @include *
// @version 1
// @run-at document-start
// ==/UserScript==
var observer = new MutationObserver(function(mutations)
{
mutations.forEach(function(mutation)
{
if (mutation.target.getAttribute('class') == 'nav')
GM_log('nav creation');
});
});
observer.observe(document, {subtree: true, attributes: true, attributeFilter: ['class']});
我也试过了。
// ==UserScript==
// @name ii-shortcuts
// @namespace https://github.com/RedHatter
// @include *
// @version 1
// @run-at document-start
// ==/UserScript==
var observer = new MutationObserver(function(mutations)
{
mutations.forEach(function(mutation)
{
if (mutation.addedNodes[0].getAttribute('class') == 'nav')
GM_log('nav creation');
});
});
observer.observe(document, {subtree: true, childList: true});
但是在下面的情况下,“导航创建”登录页面加载。我错过了什么?
答案 0 :(得分:8)
几个问题(从大到小):
文档第一次时,静态加载;事件是childList
个事件,而不是attributes
个事件。
例如,
$("body").append ('<p id="foo" class="bar">Hiya!</p><p>blah</p>');
生成一个 childList
事件,而后续
$("#foo").attr ("class", "bar2");
生成attributes
事件
mutation.addedNodes[0]
包含类nav
的元素的几率几乎为零。这几乎总是一个文本节点
你需要检查整个数组,加上target
。
不要使用getAttribute('class') == 'nav'
来检查课程。这将为没有getAttribute
函数的节点抛出异常,并且它会遗漏具有多个类的元素。 EG:<p class="foo nav bar">...
在适当的节点类型上使用classList.contains()
。
如果您使用@grant
之类的GM_
函数,请使用GM_log()
指令。无论如何都要使用授权,以确保沙箱保持开启。
避免使用// @include *
。特别是对于计时器和观察者,这可能会使浏览器和机器陷入困境。
此信息适用于Firefox。 Chrome在实现Mutation观察者方面存在很大差异。在加载页面之前,此类代码无法在Chrome中使用。
将所有内容放在一起,脚本变为:
// ==UserScript==
// @name _ii-shortcuts
// @namespace https://github.com/RedHatter
// @include http://YOUR_SERVER.COM/YOUR_PATH/*
// @run-at document-start
// @version 1
// @grant GM_log
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
introduced in GM 1.0. It restores the sandbox.
*/
var MutationObserver = window.MutationObserver;
var myObserver = new MutationObserver (mutationHandler);
var obsConfig = {
childList: true, attributes: true,
subtree: true, attributeFilter: ['class']
};
myObserver.observe (document, obsConfig);
function mutationHandler (mutationRecords) {
mutationRecords.forEach ( function (mutation) {
if ( mutation.type == "childList"
&& typeof mutation.addedNodes == "object"
&& mutation.addedNodes.length
) {
for (var J = 0, L = mutation.addedNodes.length; J < L; ++J) {
checkForCSS_Class (mutation.addedNodes[J], "nav");
}
}
else if (mutation.type == "attributes") {
checkForCSS_Class (mutation.target, "nav");
}
} );
}
function checkForCSS_Class (node, className) {
//-- Only process element nodes
if (node.nodeType === 1) {
if (node.classList.contains (className) ) {
console.log (
'New node with class "' + className + '" = ', node
);
// YOUR CODE HERE
//GM_log ('nav creation');
}
}
}
答案 1 :(得分:0)
请注意mutation.addedNodes
返回null - 在这种情况下,此代码将失败。尝试:
if (mutation.addedNodes && mutation.addedNodes[0].getAttribute('class') === 'nav') {
...
变异对象还有一个'type'属性,可用于获取更多信息;您是否阅读了MDN上的API文档?那里有一些很好的例子。