簡體   English   中英

錯誤:jQuery 需要一個帶有文檔的窗口

[英]Error: jQuery requires a window with a document

因此,在進行 npm update 之前,一切都工作得很好,現在一切都不像以前那樣工作了。

一點背景知識:在我的代碼中,我使用 jquery 來解析文本 html。 我不使用窗口,也不使用 jsdom。 它曾經很好地做到這一點:

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

但現在我明白了:jQuery 需要一個帶有文檔的窗口

我該如何解決?

這對我有用

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

node.js-jQuery 定義在一行中:

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

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

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不再工作。

我解決了。 必須先刪除 jsdom 和 jquery,然后 npm install jsdom jquery。

然后這個:

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

事實證明,我擁有最新版本很重要。 不然沒用。。

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

您可以在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>

(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. 加載外部腳本
  2. 加載本地腳本

我將它放在我的 Node.js(服務器)文件的頂部,該文件使用 jQuery 來幫助呈現 html 文本......

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

一切都是玫瑰。

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 選擇器函數

您必須提供一個窗口對象。 為此,只需從 jsdom 傳遞 parentWindow:

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

我知道我在這里的年份不正確,但我可能找到了更好的方法,然后是這里提供的方法。 如果您從 .html 文件調用腳本,腳本將知道該文檔,並且它為我解決了問題(至少目前如此)。 例子:

索引.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);

讓我知道它是否錯了,我今天才開始使用這個框架。

我目前正在使用這種方式:檢查jsdom 的文檔

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

我在 node 命令行上使用了 neoRiley 的 2 行,並在命令行上測試了 jQuery Promise。 通過 npm // https://github.com/UncoolAJ86/node-jquery將 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();

承諾解析成功回調,“開始游戲..”將打印控制台輸出

Starting game..

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM