【问题标题】:Getting DOM object fails with jQuery in content script在内容脚本中使用 jQuery 获取 DOM 对象失败
【发布时间】:2025-12-13 15:10:01
【问题描述】:

我在谷歌页面中有一个按钮。 DOM Inspector 给出它的 id。但是尝试获取对象失败。我在控制台中绑定类名时得到 undefined 结果。页面中只有一个 iframe,我的对象不在其中(据我所知)。

ma​​nifest.json:

{
    "manifest_version": 2,
    "name": "modify strings",
    "description": "modify strings in bulk",
    "version": "1.0",
    "permissions": [
       "tabs",
       "history",
       "http://*/*",
       "https://*/*"
    ],  

    "content_scripts": [
        {
            "matches": ["https://play.google.com/apps/*"],
            "js": ["jquery-1.11.1.min.js", "myInject.js"],
            "all_frames": true
        }
    ],

    "web_accessible_resources": [
        "script.js",
        "jquery-1.11.1.min.js"
    ],

    "browser_action": {
        "default_icon": "icon.png",
        "default_popup": "popup.html"
    }



}

myInject.js(内容脚本):

var buttonJGET = jQuery("gwt-uid-115", document);   
console.log(buttonJGET.className);

【问题讨论】:

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


    【解决方案1】:

    jQuery 使用CSS-like selectors

    select element by its id,你需要使用#。 此外,jQuery 总是返回一个结果数组,即使它是唯一的。

    var buttonJGET = jQuery("#gwt-uid-115")[0];
    

    jQuery 元素不同于 DOM 元素;他们没有className 属性。 要获得它,可以使用,例如:

    console.log(buttonJGET.attr('class'));
    

    还有other functions to deal with elements' classes

    否则你可以extract a DOM element out of a jQuery element:

    var buttonJGET = jQuery("#gwt-uid-115").get(0);
    console.log(buttonJGET.className);
    

    如果代码仍然失败,可能是因为在脚本运行时没有具有该 id 的元素(目前)。要实现“每次添加时运行我的代码”,可以使用DOM mutation observers(规范答案here):

    // Runs a function for every added DOM element that matches a filter
    // filter -- either function(DOM_node){/*...*/}, returns true or false 
    //           OR a jQuery selector
    // callback -- function(DOM_node){/*...*/}
    function watchNodes(filter, callback){
      var observer = new MutationObserver( function (mutations) {
        mutations.forEach( function (mutation){
          if(typeof filter === "function"){
            $(mutation.addedNodes).filter(
              function(i){ return filter(this); }
            ).each(
              function(i){ callback(this); }
            );
          } else {
            $(mutation.addedNodes).filter(filter).each(
              function(i){ callback(this); }
            );
          }
        });
      });
    
      // For every added element, a mutation will be processed
      //   with mutation.taget == parent
      //   and mutation.addedNodes containing the added element
      observer.observe(document, { subtree: true, childList: true });
    
      return observer;
    }
    

    使用(注意,过滤器和回调使用 DOM 元素):

    function logger(node) {
      console.log(node.className); 
    }
    
    var observer = watchNodes("#gwt-uid-115", logger);
    

    或者,例如,如果您想捕获 id 以 gwt-uid 开头的所有节点,您可以编写自定义过滤器:

    function filter(node) {
      if(node.id && node.id.match(/^gwt-uid/)) return true;
      else return false;
    }
    
    var observer2 = watchNodes(filter, logger);
    

    将其注入run_at: "document_start" 将确保您捕获所有添加的元素。

    要停止观察,请在返回的观察者对象上调用observer.disconnect()

    【讨论】:

    • 使用了各种前置程序仍然无法正常工作。所以我使用了 var buttonJGET = jQuery("#gwt-uid-115");但不工作,仍然给我 undefined ,我已经正确地重新加载了扩展。
    • 更新了我的答案,但请不要编辑掉你的问题:Stack Overflow 应该是问题答案的记录。
    • 谢谢,我已经编辑回原来的样子了;我已输入您的更正,但现在出现错误:“未捕获的类型错误:无法读取未定义的属性 'className'”
    • 这意味着没有具有该 id 的元素,至少在查询执行的那一刻(你会同意它看起来是动态的)。您需要围绕这种可能性重新考虑您的代码。但我认为您的原始问题已得到解答。
    • 我需要在清单中添加什么作为 run_at 字段,以便脚本在所有可能的时间运行?