在'MutationObserver'上'观察':参数1不是'Node'类型

gee*_*har 19 javascript gmail google-chrome-extension mutation-observers gmail-api

我正在创建Chrome扩展程序,并尝试在gMail撰写框的SEND按钮旁边添加一个小文本.

我正在使用MutationObserver来了解撰写框窗口何时出现.我通过观察一个带有类的元素来做这个,no因为compose box元素被创建为这个元素(class no)的子元素.

当用户单击撰写按钮并出现撰写框窗口时,我会使用该.after()方法在SEND按钮旁边放置一个元素.发送按钮类名称是.gU.Up.

这些是gMail的真正类名,也很奇怪.

以下是我使用的代码:

var composeObserver = new MutationObserver(function(mutations){ 
    mutations.forEach(function(mutation){
        mutation.addedNodes.forEach(function(node){
            $(".gU.Up").after("<td> <div> Hi </div> </td>");
        });
    });
});

var composeBox = document.querySelectorAll(".no")[2];
var config = {childList: true};
composeObserver.observe(composeBox,config);
Run Code Online (Sandbox Code Playgroud)

问题是我经常遇到以下错误:

Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'
Run Code Online (Sandbox Code Playgroud)

有人可以帮忙吗?我已经尝试了很多东西,并在这里查看了其他答案,但仍然无法摆脱这个错误.

这是我的manifest.json文件:

{
    "manifest_version": 2,
    "name": "Gmail Extension",
    "version": "1.0",

    "browser_action": {
        "default_icon": "icon19.png",   
        "default_title": "Sales Analytics Sellulose"    
    },

    "background": {
        "scripts": ["eventPage.js"],
        "persistent": false
    },

    "content_scripts": [
    {
        "matches": ["https://mail.google.com/*"],
        "js": ["jquery-3.1.1.js", "insQ.min.js", "gmail_cs.js"]
    }
],

    "web_accessible_resources":[
        "compose_icon.png",
        "sellulosebar_icon.png" 
    ]
}
Run Code Online (Sandbox Code Playgroud)

PS我已经尝试过插入查询库,但它有一些缺点.它不会让我具体说明具体要素的变化.我还没有尝试使用mutationummary库,但由于它使用MutationObserver,我认为问题会持续存在.

从评论中添加:
选择器确实没有给我一个节点.我检查了控制台,它给了一个对象.我还检查了控制台,并选择了我想要观察的相应元素.

但是,当我console.log为所选元素添加时,它显示为未定义.这意味着,在节点出现之前,您可能正确执行代码.你能告诉我如何确保延迟发生吗?'setTimeout'会工作吗?在MutationObserver的情况下它是如何工作的?

Mak*_*yen 17

正如我在评论中提到的那样,Xan给出了一个答案,错误清楚地表明结果document.querySelectorAll(".no")[2]不会评估到Node.

根据您在注释中提供的信息,很明显问题是您的代码执行时您想要观察的节点不存在.在该节点可用之前,有许多方法可以延迟代码的执行.一些可能性是:

  1. 使用setTimeout循环进行轮询,直到您检测到要放置MutationObserver的元素可用:

    function addObserverIfDesiredNodeAvailable() {
        var composeBox = document.querySelectorAll(".no")[2];
        if(!composeBox) {
            //The node we need does not exist yet.
            //Wait 500ms and try again
            window.setTimeout(addObserverIfDesiredNodeAvailable,500);
            return;
        }
        var config = {childList: true};
        composeObserver.observe(composeBox,config);
    }
    addObserverIfDesiredNodeAvailable();
    
    Run Code Online (Sandbox Code Playgroud)

    这将在DOM中存在之后相对较短的时间找到相应的节点.此方法的可行性取决于插入目标节点后需要多长时间才能将观察者置于其上.显然,您可以根据需要调整轮询尝试之间的延迟.

  2. 创建另一个MutationObserver以在DOM中更高的位置观察祖先节点,以插入要放置主观察者的节点.虽然这会在插入时立即找到合适的节点,但它可能非常耗费资源(CPU),具体取决于您必须观察的DOM的高度以及DOM更改的活动量.


小智 7

尝试与jQuery一起使用。

如果您正在开发Chrome扩展程序,并且从content_script中的页面或DOM中获取HTML元素(节点),则将获得Object,并且Node将作为Object的属性返回。然后,您可以从Object获取Node并传递给observe(Node,config)方法。

var node = $("#elementId");  //this is wrong because if you logged this in the console you will get Object

var node = $("#elementId")[0];  //This gives the first property of the Object returned, and this is correct because if you logged this in the console you will get the Node element for which you want to detect changes in the DOM.
Run Code Online (Sandbox Code Playgroud)


Xan*_*Xan 5

此错误意味着它document.querySelectorAll(".no")[2]不是Node.

这很可能意味着没有这样的元素;querySelectorAll将始终返回 a NodeList,即使它是空的;访问不存在的列表成员会成功而不会出现运行时错误,但返回undefined: 在这个意义上,NodeList就像一个数组。

“等等,但它确实如此!我在控制台中运行了这段代码,它工作正常!” 你可能会惊呼。那是因为在您执行它时,在文档完成加载很久之后,这些元素就存在了。

所以,你需要等待这个根元素被添加;可能,与另一个人MutationObserver一起完成这项工作。