错误:jQuery需要一个带文档的窗口

时间:2014-01-26 00:17:56

标签: jquery node.js

所以一切都很好,直到做npm更新,现在事情不像以前那样有效。

一点背景:在我的代码中,我使用jquery来解析文本html。我不使用窗口,我不使用jsdom。过去工作得很好:

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

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

我该如何解决这个问题?

13 个答案:

答案 0 :(得分:34)

node.js-jQuery定义在一行:

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

// usage
$("body").append("<div>TEST</div>");
console.log($("body").html());

答案 1 :(得分:15)

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 :(得分:10)

这对我有用

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

答案 3 :(得分:9)

我解决了。不得不首先删除jsdom和jquery然后npm安装jsdom jquery。

然后这个:

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

事实证明,我拥有最新版本非常重要。否则它不起作用..

答案 4 :(得分:4)

(2018) - 新的jsdom API

  if(isset($var)){
      // do something
  }

参考文献:

  1. Loading external scripts
  2. Loading local scripts

答案 5 :(得分: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>

答案 6 :(得分:3)

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

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

一切都出现了玫瑰。

答案 7 :(得分:3)

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

答案 8 :(得分:2)

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 以获得一个 window 对象。然后使用 jquery 包装所述窗口对象

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

答案 9 :(得分:0)

您必须提供一个窗口对象。要做到这一点,只需从jsdom传递parentWindow:

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

答案 10 :(得分:0)

我知道我今年没有在正确的一年,但我可能找到了更好的方式,然后是这里提供的方式。如果从.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>

initialize.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 :(得分:-1)

我目前正在使用这种方式:检查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());
    });
  }
});

答案 12 :(得分:-1)

我在节点命令行上使用了neoRiley的2行,并在命令行上测试了jQuery promise。 通过npm向节点命令行添加了jquery // http://developer.android.com/tools/help/adb.html#Enabling获取指示。

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

/ home / sridhar $ node

// 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();

承诺解决成功回调,&#39;开始游戏..&#39;将被打印 控制台输出

Starting game..