【问题标题】:Error: jQuery requires a window with a document错误:jQuery 需要一个带有文档的窗口
【发布时间】:2014-02-16 22:38:04
【问题描述】:

所以在进行 npm update 之前,一切都运行良好,现在一切都不像以前那样运行了。

一点背景知识:在我的代码中,我使用 jquery 来解析文本 html。我不使用窗口,也不使用 jsdom。它曾经很好地做到这一点:

$ = require("jquery"); 
$(html).find("<h1>").html("The title"); 

但现在我明白了: jQuery 需要一个带有文档的窗口

我该如何解决这个问题?

【问题讨论】:

  • 这个话题是我讨厌 JS 的原因。一切都已弃用和损坏。

标签: jquery node.js


【解决方案1】:

jQuery 的 npm 包肯定会包含 jsdom,这就是为什么它可以在 Node 中工作:jQuery 需要有某种 DOM 环境才能使用。

您可以通过npm install jquery@1.8.3 来检查旧版本是否曾经拥有它。你会看到 jsdom 被安装了。出于某种原因,他们似乎已经从最近的版本中删除了 jsdom。我不知道为什么。

但是,使用 jsdom 7.x 运行 jQuery 代码很简单:

var jsdom = require("jsdom");
var window = jsdom.jsdom().defaultView;

jsdom.jQueryify(window, "http://code.jquery.com/jquery.js", function () {
  var $ = window.$;
  $("body").prepend("<h1>The title</h1>");
  console.log($("h1").html());
});

路径可以更改为不同版本的 jQuery 或本地文件。

注意:早期版本的 jsdom,包括 3.x 系列,需要 var window = jsdom.jsdom().parentWindow; 行而不是 var window = jsdom.jsdom().defaultView;。 4.x 使parentWindow 不再起作用。

【讨论】:

    【解决方案2】:

    我解决了。必须先删除 jsdom 和 jquery,然后 npm install jsdom jquery。

    然后这个:

    var jsdom = require("jsdom"); 
    $ = require("jquery")(jsdom.jsdom().createWindow()); 
    

    事实证明,拥有最新版本很重要。否则它没有工作..

    【讨论】:

    • 这不适用于我的版本 (v0.10.28) 以及当前的 jquery 和 jsdom 模块。
    • @Michael 你必须使用parentWindow 属性。 createWindow() 不存在。
    【解决方案3】:

    您可以在package.json 中使用这些版本设置尝试以下操作:

    "jquery": "^2.1.1",
    "jsdom": "^1.0.0-pre.3"
    

    假设你有一个名为page.htm的文件:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <h1>Html page</h1>
        <div class="left">
            <p>left content</p>
        </div>
    </body>
    </html>
    

    然后,您可以从文件中读取,使用 JSDOM 从中创建一个 DOM 和窗口并将其传递给 jquery:

    var jsdom = require("jsdom").jsdom;
    var fs = require('fs');
    fs.readFile('page.htm', {encoding: "utf8"}, function (err, markup) {
      if (err) throw err;
      var doc = jsdom(markup);
      var window = doc.parentWindow;
      var $ = require('jquery')(window)
      var outerLeft = $(".left").clone().wrap('<div></div>').parent().html();
      var innerLeft = $(".left").html();
      console.log(outerLeft, "and ...", innerLeft);
    });
    

    将输出:

    <div class="left">
    <p>left content</p>
    </div> and ... 
    <p>left content</p>
    

    【讨论】:

      【解决方案4】:

      我将它放在我的 Node.js(服务器)文件的顶部,该文件使用 jQuery 来帮助呈现 html 文本...

      var jsdom = require("jsdom").jsdom;
      jsdom.env({
          html : "<html><body></body></html>",
          done : function(errs, window) {
              global.window = window;
          }
      });
      

      一切都如愿以偿。

      【讨论】:

        【解决方案5】:

        您必须提供一个窗口对象。为此,只需从 jsdom 传递 parentWindow:

        var jsdom = require("jsdom"); 
        var $ = require("jquery")(jsdom.jsdom().parentWindow);
        

        【讨论】:

          【解决方案6】:

          我目前正在使用这种方式:查看jsdom's documentation

           var html = fs.readFileSync("./your_html_file.html");
          
           jsdom.env({
            //url: "http://url_here", //in case you want to load specific url 
            //html property is used in case of you need to load html string here
            html: html,
            scripts: ["http://code.jquery.com/jquery.js"],
            done: function (err, window) {
              var $ = window.$;
              //start using jquery now 
              $("p").each(function(index) {
                console.log("paragraph ", index, $(this).text());
              });
            }
          });
          

          【讨论】:

            【解决方案7】:

            我在 node 命令行上使用了 neoRiley 的 2 行,并在命令行上测试了 jQuery Promise。 通过 npm 将 jquery 添加到节点命令行 //https://github.com/UncoolAJ86/node-jquery 获取说明。

            npm install -S 'jquery@>=2.1'
            npm install -S 'jsdom@3.1.2'
            

            /home/sridhar$ 节点

            // make $ available on node commandline
            >var jsdom = require("jsdom"); 
            >var $ = require("jquery")(jsdom.jsdom().parentWindow);
            >var promise = new $.Deferred();
            >promise.done(function(){console.log('Starting game ..');});
            >promise.resolve();
            

            promise 解析为成功回调,'Starting game ..' 将被打印 控制台输出

            Starting game..
            

            【讨论】:

              【解决方案8】:

              (2018) - 新的 jsdom API

              var jsdom = require('jsdom'),
                  { JSDOM } = jsdom,
                  jsdom_options = {
                    runScripts: "dangerously",
                    resources: "usable"
                  };
              
              // external script example:
              var DOM = new JSDOM(`<!DOCTYPE html><html><head><script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script></head><body></body></html>`, jsdom_options);
              
              // local script example:
              var jQuery = fs.readFileSync("../../jQuery.js", { encoding: "utf-8" });
              var DOM = new JSDOM(``, { runScripts: "dangerously" });
              
              var scriptElm = window.document.createElement("script");
              scriptElm.textContent = jQuery;
              DOM.window.document.head.appendChild(scriptElm);
              

              参考资料:

              1. Loading external scripts
              2. Loading local scripts

              【讨论】:

                【解决方案9】:

                这对我有用

                var jsdom = require('jsdom');
                $ = require('jquery')(new jsdom.JSDOM().window);
                

                【讨论】:

                • 当我向下滚动时,我不得不尝试几种不同的方法,直到我发现这个......在某些时候jsdom 一定已经改变了。这是使用当前版本的jsdom 的方法
                • 是的。其他答案对我不起作用。只有这一个。
                【解决方案10】:

                我知道我在这里的年份不正确,但我可能找到了更好的方法,然后是这里提供的方法。如果您从 .html 文件调用脚本,脚本将知道该文档,并且它为我解决了问题(至少目前如此)。示例:

                index.html:

                <html>
                <head>
                <meta charset="UTF-8">
                <!--Scripts-->
                <script>
                    window.$ = window.jQuery = require('../js/libs/jQuery.js');
                </script>
                <script src="../js/libs/materialize.js"></script>
                <script>
                    const init = require("../js/initialize/initialize.js");
                    init.initializer.main_init();
                </script>
                
                <!--Styles-->
                <!--Libraries-->
                <link rel="stylesheet" href="../scss/libs/materialize.css" />
                </head>
                </html>
                

                初始化.js:

                var jQuery = require('jquery');
                
                (function($, global, undefined) {
                    "use strict";
                
                    var Initialize = function() {
                        var initializer;          
                        initializer = {
                            materialize_init: function () {
                            console.log(document.getElementsByClassName("tooltipped"));
                            },
                
                            main_initialize: function () {
                                this.materialize_init();
                            }
                        };
                
                        return {
                            main_init: function () {
                                initializer.main_initialize();
                                return this;
                            }
                        };
                    };
                
                    // AMD and window support
                    if (typeof define === "function") {
                        define([], function () { return new Initialize(); });
                    } else if (typeof global.initializer === "undefined") {
                        global.initializer = new Initialize();
                    }
                
                })(jQuery, this);
                

                如果有错请告诉我,我今天才开始使用这个框架。

                【讨论】:

                  【解决方案11】:

                  jsdom 似乎有一个新版本,因此现在它的工作方式略有不同。这里有一个例子:

                  const { JSDOM } = require("jsdom");
                  const myJSDom = new JSDOM (html);
                  const $ = require('jquery')(myJSDom.window);
                  

                  现在您可以像以前在 jQuery 上一样进行搜索了:

                  $("<h1>").html("The title");
                  

                  注意 jQuery 安装,因为您应该将 jquery 全部小写,如 npm install jquery

                  【讨论】:

                    【解决方案12】:

                    2021年答案

                    最近遇到同样的问题

                    这适用于“jquery”:“^3.5.1”和“jsdom”:“^16.4.0”

                    const jsdom = require("jsdom");
                    const { JSDOM } = jsdom;
                    const jquery = require('jquery')
                    
                    getHtmlFromSomewhere(function (err, data) {
                        handleError(err)
                        
                        console.log("html is ", data)
                        const dom = new JSDOM(data);
                    
                        const $ = jquery(dom.window);
                        const someData = $("#dataTable tbody tr:last td:eq(1)")
                    
                        console.log("some data is: ", someData.text())
                    });
                    
                    

                    解决方案的要点是使用 JSDOM 解析 HTML 以获得窗口对象。然后使用 jquery 包装所述窗口对象

                    就是这样,你可以在解析的文档中使用jquery选择器函数

                    【讨论】:

                      猜你喜欢
                      • 2017-08-29
                      • 2017-10-22
                      • 2019-10-21
                      • 1970-01-01
                      • 1970-01-01
                      • 2013-12-21
                      • 2020-08-19
                      • 2018-07-05
                      • 1970-01-01
                      相关资源
                      最近更新 更多