MutationObserver错误:我怎么能等待创作元素的? [重复]

问题描述 投票:0回答:3

这个问题已经在这里有一个答案:

我试图做出的Greasemonkey脚本,在Facebook页面添加一个按钮。但我需要等待创作元素的添加就可以了按钮。 我试图用MutationObserverAs suggested here)做,但有错误。

function init() {
    console.log('Launched : ' + launched);
    if (!launched) {
        launched = true;
        main();
    }
}
console.log('barfoo');

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        if (!mutation.addedNodes) return;
        console.log(mutation.addedNodes.type());
        for (var i = 0; i < mutation.addedNodes.length; i++) {
            if (mutation.addedNodes[i].matches('div[class="pam _5shk uiBoxWhite bottomborder"]')) {
                console.log('init');
                init();
            }
        }
    })
});
console.log('bar');

try {
    observer.observe(document.body, {
        childlist: true,
        subtree: true,
        attributes: false,
        characterData: false,
    });
} catch (error) {
    console.log(error);
}
console.log('foobar');

但我得到了以下日志:

barfoo
bar
DOMException [TypeError: "The expression cannot be converted to return the specified type."
code: 0
nsresult: 0x805b0034
location: file:///home/vmonteco/.mozilla/firefox/f3xgmo8e.default/gm_scripts/Facebook_cleaner/Facebook_cleaner.user.js:230] Facebook_cleaner.user.js:239:3
foobar

这是什么错误的原因是什么?我怎么能解决这个问题?

如果该元素是我的脚本执行前创建的,将MutationObserver仍然被触发? (即,如果该元件已经当我创建MutationObserver存在)。

注:我试图用$(document).ready(),但它创造我想要添加的按钮元素之前触发。

注二:我没有张贴整个脚本。

javascript firefox greasemonkey mutation-observers
3个回答
7
投票

该错误信息使用完全模糊的不幸,但你有一个错字:

observer.observe(document.body, {
  childlist: true,
  subtree: true,
  attributes: false,
  characterData: false,
});

应该

observer.observe(document.body, {
  childList: true,
  subtree: true,
  attributes: false,
  characterData: false,
});

例如childlist => childList

在这种情况下,在Chrome中运行的相同的代码提供了一个更有帮助的消息不是“不能转换返回指定的类型”。它说

选项对象必须设置的“属性”,“characterData”至少一个,或“的childList”为真。


1
投票

其实,MutationObserver是不是要做到这一点的最佳方式(如你正在学习的艰辛的道路。它很快变得复杂和脆弱。它真的可以拖垮一个网页,这不是跨平台的一致性)。 另外,如果你的元素脚本火灾之前就存在,MutationObserver不会赶上它。

使用像如图Run Greasemonkey script on the same page, multiple times?的方法。

就这样,你的整个脚本变为:

// ==UserScript==
// @name     _Wait for specific divs
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/
waitForKeyElements (
    'div.pam _5shk.uiBoxWhite.bottomborder', processDiv
);

function processDiv (jNode) {
    //  YOUR CODE HERE.
    // For example:
    jNode.css ("background", "pink");
}

看得出来是多么容易! :) 随着waitForKeyElements()您可以根据需要使用任何复杂的jQuery选择。


如果你真的坚持MutationObservers,使用花费的痛苦了它的库。 This answer shows how to use MutationObserver in a Greasemonkey/Tampermonkey script.


-1
投票

我看到一种意见认为MutationObserver不是办法做到这一点,但实际上,它是。细微差别是,如果你要处理的是加载从一开始就正确,页面的节点,然后不会错过任何东西,你必须运行与// @run-at document-start条件猴脚本,然后例如附加观察者到document.documentElement赶上绝对一切(或者,如果你确信nonthing将在页面以后更改会破坏这个稍后出现的元素):

(function()
{
  new MutationObserver((mutationsList, observer) => { 
    for (let mutation of mutationsList)
    {
      if (mutation.type != 'childList' || !mutation.addedNodes.length)
      {
        continue;
      } 
      Array.from(mutation.addedNodes).forEach(function(e) // or forSome if you only want to catch one object such as a button
      {
        if (!(e instanceof Element))
        {
          return;
        }
        // do stuff
      });  
    }
  }).observe(document.documentElement, {childList: true, subtree: true});
})();
© www.soinside.com 2019 - 2024. All rights reserved.