我可以将jQuery与Node.js一起使用吗?


574

是否可以使用Node.js在服务器端使用jQuery选择器/ DOM操作?


3
我想知道:为什么要在服务器端使用而又可以在客户端使用呢?
伊南克·古姆斯

31
也许您可能想要创建一个Web抓取工具,该抓取工具会定期抓取特定信息并将结果存储在数据库中?从客户端来看,这不太实际。
Trevor 2014年

2
您还应该看看phantomjs,它允许您使用V8引擎模拟浏览器服务器端。
Dimitri Kopriwa 2015年

2
在制作搜寻器时,服务器端的@deeperx DOM操作可能很有用。看到这个答案
Lucio Paiva 2015年

是的-看一下这个答案 -我更喜欢使用cheerio,因为您可以获得jQuery选择器的全部功能。
monika mevenkamp

Answers:


563

更新(18-Jun-18):似乎有一个重大更新jsdom,导致原来的答案不再起作用。我找到了这个答案,解释了如何使用jsdom现在。我已经在下面复制了相关代码。

var jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
global.document = document;

var $ = jQuery = require('jquery')(window);

注意:原始答案没有提及您还需要使用安装jsdomnpm install jsdom

更新(2013年末):官方jQuery团队终于jquery在npm上接管了该软件包的管理:

npm install jquery

然后:

require("jsdom").env("", function (err, window) {
    if (err) {
        console.error(err);
        return;
    }
    var $ = require("jquery")(window);
});


43
是否可以在该npm模块中使用来自node.js的jQuery ajax?
2011年

22
不会安装在Windows上(无需大量工作),在这种情况下,我建议使用Cheerio
Simon East

7
+1表示在哪里获取npm :)大多数人有一个坏习惯,就是仅仅提一些东西,就像应该给定的一样(常识)
2013年

12
这返回require("...").env is not a function
班德里

4
@Banderi和我一样,有什么想法吗?错误:TypeError: require(...).env is not a function
coderInrRain

58

是的,可以使用我创建的名为nodeQuery的库

var Express = require('express')
    , dnode = require('dnode')
    , nQuery = require('nodeQuery')
    , express = Express.createServer();

var app = function ($) {
    $.on('ready', function () {
        // do some stuff to the dom in real-time
        $('body').append('Hello World');
        $('body').append('<input type="text" />');
        $('input').live('click', function () {
            console.log('input clicked');
            // ...
        });
    });
};

nQuery
    .use(app);

express
    .use(nQuery.middleware)
    .use(Express.static(__dirname + '/public'))
    .listen(3000);

dnode(nQuery.middleware).listen(express);

20
请注意,nodeQuery实际上是在实时更改用户页面,因此它甚至比人们期望的还要酷。
alessioalex 2011年

当我偶然发现这里时,我正在搜索类似的内容...我刚刚看过nQuery和jquery节点包,而nQuery是在一年前更新的,昨天是jquery ... nQuery不再开发了吗?jQuery是否会像nQuery一样影响客户端?有人尝试过它们吗?
Logan

2
@Logan nQuery基本上只是jquery。区别在于代码在服务器上运行,而不是将jquery代码传递给浏览器,而是在服务器上运行代码,并远程对连接的浏览器执行dom操作。还要注意,nQuery是一个实验性项目,尽管我将接受拉取请求以修复错误,但它从未为任何特定目的或项目而创建,因此它没有很多提交
Thomas Blobaum 2012年

@ThomasBlobaum不是为我工作,错误:, express = Express.createServer();TypeError: Express.createServer is not a function任何想法?
coderInrRain

@ThomasBlobaum似乎您没有最新版本的Express。npm install --save express在命令提示符下尝试。
吉尔伯特五世

55

在撰写本文时,还保留了Cheerio

专为服务器设计的核心jQuery的快速,灵活和精益实现。


2
+1为Cheerio。另一方面,jsdom很难在Windows上运行。
西蒙东

1
Cheerio可以使用延迟事件和Ajax调用吗?
霍夫曼2014年

6
不支持很多选择器,例如:gt(1)
chovy

1
以我的经验,这是最好的。它比JSDOM快很多。
杰森·普兰

1
@霍夫曼,我花了一秒钟时间为您检查文档。不,不是的。Cheerio仅具有与DOM相关的方法。
丹尼斯


34

使用Cheerio的简单爬虫

这是我在Node.js中创建简单爬网程序的公式。这是想要在服务器端进行DOM操作的主要原因,这也许就是您来到这里的原因。

首先,用于request下载要解析的页面。下载完成后,cheerio像使用jQuery一样处理它并开始DOM操作。

工作示例:

var
    request = require('request'),
    cheerio = require('cheerio');

function parse(url) {
    request(url, function (error, response, body) {
        var
            $ = cheerio.load(body);

        $('.question-summary .question-hyperlink').each(function () {
            console.info($(this).text());
        });
    })
}

parse('http://stackoverflow.com/');

此示例将在控制台上显示SO主页上显示的所有最重要的问题。这就是为什么我喜欢Node.js及其社区。没有比这更容易的了:-)

安装依赖项:

npm安装请求cheerio

并运行(假设上面的脚本在file中crawler.js):

节点crawler.js


编码方式

某些页面会以某种编码包含非英语内容,您需要将其解码为UTF-8。例如,巴西葡萄牙语(或拉丁语来源的任何其他语言)的页面很可能会以ISO-8859-1(aka“ latin1”)编码。当需要解码时,我告诉我request不要以任何方式解释内容,而是使用它iconv-lite来完成工作。

工作示例:

var
    request = require('request'),
    iconv = require('iconv-lite'),
    cheerio = require('cheerio');

var
    PAGE_ENCODING = 'utf-8'; // change to match page encoding

function parse(url) {
    request({
        url: url,
        encoding: null  // do not interpret content yet
    }, function (error, response, body) {
        var
            $ = cheerio.load(iconv.decode(body, PAGE_ENCODING));

        $('.question-summary .question-hyperlink').each(function () {
            console.info($(this).text());
        });
    })
}

parse('http://stackoverflow.com/');

在运行之前,请安装依赖项:

npm安装请求iconv-lite cheerio

最后:

节点crawler.js


以下链接

下一步将是链接。假设您要列出SO每个最重要问题的所有发帖人。您必须首先列出所有热门问题(上面的示例),然后输入每个链接,解析每个问题的页面以获取涉及的用户列表。

当您开始关注链接时,回调地狱就可以开始。为了避免这种情况,您应该使用某种承诺,期货或其他任何方式。我总是在工具带中保持异步。因此,这是使用异步的搜寻器的完整示例:

var
    url = require('url'),
    request = require('request'),
    async = require('async'),
    cheerio = require('cheerio');

var
    baseUrl = 'http://stackoverflow.com/';

// Gets a page and returns a callback with a $ object
function getPage(url, parseFn) {
    request({
        url: url
    }, function (error, response, body) {
        parseFn(cheerio.load(body))
    });
}

getPage(baseUrl, function ($) {
    var
        questions;

    // Get list of questions
    questions = $('.question-summary .question-hyperlink').map(function () {
        return {
            title: $(this).text(),
            url: url.resolve(baseUrl, $(this).attr('href'))
        };
    }).get().slice(0, 5); // limit to the top 5 questions

    // For each question
    async.map(questions, function (question, questionDone) {

        getPage(question.url, function ($$) {

            // Get list of users
            question.users = $$('.post-signature .user-details a').map(function () {
                return $$(this).text();
            }).get();

            questionDone(null, question);
        });

    }, function (err, questionsWithPosters) {

        // This function is called by async when all questions have been parsed

        questionsWithPosters.forEach(function (question) {

            // Prints each question along with its user list
            console.info(question.title);
            question.users.forEach(function (user) {
                console.info('\t%s', user);
            });
        });
    });
});

运行之前:

npm安装请求异步cheerio

运行测试:

节点crawler.js

样本输出:

Is it possible to pause a Docker image build?
    conradk
    Thomasleveil
PHP Image Crop Issue
    Elyor
    Houston Molinar
Add two object in rails
    user1670773
    Makoto
    max
Asymmetric encryption discrepancy - Android vs Java
    Cookie Monster
    Wand Maker
Objective-C: Adding 10 seconds to timer in SpriteKit
    Christian K Rider

这就是您开始制作自己的搜寻器的基本知识:-)


使用的图书馆


22

在2016年,事情变得更加轻松。使用控制台将jquery安装到node.js:

npm install jquery

将其绑定到$您的node.js代码中的变量(例如-我已经习惯了):

var $ = require("jquery");

做东西:

$.ajax({
    url: 'gimme_json.php',
    dataType: 'json',
    method: 'GET',
    data: { "now" : true }
});

由于它基于node.js,因此也适用于gulp。


您正在使用哪个版本的节点?在Mac上,节点6.10.2,jquery 2.2.4 var $ = require("jquery"); $.ajax // undefined (目前暂不支持投票)。
AJP

@AJP,您确定自己npm install jquery先做过吗?
low_rents

1
是。 > console.log(require("jquery").toString());给了我工厂功能:function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } 我不得不在jsdom中使用上面的答案: stackoverflow.com/a/4129032/539490
AJP

@AJP好的,很奇怪。
low_rents

我得到与@AJP完全相同的工厂函数。您使用了哪个版本的jquery,@ low_rents?
鲍里斯·伯科夫

18

我相信现在的答案是肯定的。
https://github.com/tmpvar/jsdom

var navigator = { userAgent: "node-js" };  
var jQuery = require("./node-jquery").jQueryInit(window, navigator);

9
我很遗憾地报告说,要使jQuery在jsdom上运行还需要更多的工作。嘶嘶声确实起作用!我真的想尽可能地减少jsdom,因此,此时添加诸如env.js之类的完整浏览器仿真并不是真正的优先事项。
tmpvar

没关系,我发现与jsdom捆绑在一起的修改后的副本。
提请

现在不建议使用FYI node-jquery,而推荐使用jquery
RuslanLópez'18

1
ReferenceError:窗口未定义
波恩

17

npm install jquery --save #note所有小写

npm install jsdom --save

const jsdom = require("jsdom");
const dom = new jsdom.JSDOM(`<!DOCTYPE html>`);
var $ = require("jquery")(dom.window);


$.getJSON('https://api.github.com/users/nhambayi',function(data) {
  console.log(data);
});

这是一个很好的答案!请对此表示支持
daddinhquoc

8

可以使用以下方法安装jQuery模块:

npm install jquery

例:

var $ = require('jquery');
var http = require('http');

var options = {
    host: 'jquery.com',
    port: 80,
    path: '/'
};

var html = '';
http.get(options, function(res) {
res.on('data', function(data) {
    // collect the data chunks to the variable named "html"
    html += data;
}).on('end', function() {
    // the whole of webpage data has been collected. parsing time!
    var title = $(html).find('title').text();
    console.log(title);
 });
});

Node.js **中的jQuery引用:


2
对我不起作用... C:\ ... \\ node_modules \ jquery \ dist \ jquery.js:31抛出新错误(“ jQuery需要带有文档的窗口”);^错误:jQuery需要在module.exports(C:\ ... \ WebContent \ resources \ js \ node_modules \ jquery \ dist \ jquery.js:31:12)上有一个文档的窗口
Jose Manuel Gomez Alvarez

var jsdom = require(“ jsdom”); var window = jsdom.jsdom()。defaultView; jsdom.jQueryify(window,“ code.jquery.com/jquery.js”,function(){var $ = window。$; $(“ body”)。prepend(“ <h1>标题</ h1>”) ; console.log($(“ h1”)。html());});
SUNDARRAJAN K

7

您必须使用新的JSDOM API来获取窗口。

const jsdom = require("jsdom");
const { window } = new jsdom.JSDOM(`...`);
var $ = require("jquery")(window);

...为了支持HTML5 ,.JSDOM()应该为.JSDOM(“ <!DOCTYPE html>”)吗?
datdinhquoc

2

警告

正如Golo Roden所提到的,这种解决方案是不正确的。这只是一个快速的解决方案,可以帮助人们使用Node应用程序结构运行其实际的jQuery代码,但这不是Node的原理,因为jQuery仍在客户端而不是服务器端运行。很抱歉给您一个错误的答案。


您也可以使用node渲染Jade并将jQuery代码放入其中。这是玉文件的代码:

!!! 5
html(lang="en")
  head
    title Holamundo!
    script(type='text/javascript', src='http://code.jquery.com/jquery-1.9.1.js')
  body
    h1#headTitle Hello, World
    p#content This is an example of Jade.
    script
      $('#headTitle').click(function() {
        $(this).hide();
      });
      $('#content').click(function() {
        $(this).hide();
      });

4
拒绝投票是因为该问题明确表明它与服务器端的jQuery有关。通过简单地将jQuery嵌入到玉器文件中,jQuery仍在客户端运行。因此,此答案无济于事:-/
Golo Roden

2
好的,非常感谢。我明白了 我将尝试在答案中加以澄清,以免混淆阅读它的人们。再次感谢您对Golo的帮助。
廷贝格斯

2
别客气 :-)。没关系:我们都会犯错,所以请放心:-)
Golo Roden

2

我的工作代码是:

npm install jquery

然后:

global.jQuery   = require('jquery');
global.$        = global.jQuery;

或者,如果存在该窗口,则:

typeof window !== "undefined" ? window : this;
window.jQuery   = require('jquery');
window.$        = window.jQuery;

1

jsdom模块是一个很棒的工具。但是,如果您要评估整个页面并在服务器端对它们进行一些时髦的设计,建议您在各自的上下文中运行它们:

vm.runInContext

因此,诸如require/ CommonJS现场之类的事情不会破坏Node进程本身。

您可以在此处找到文档。干杯!


1

从jsdom v10开始,不推荐使用.env()函数。在尝试了很多需要jquery的事情之后,我像下面那样做:

var jsdom = require('jsdom');
const { JSDOM } = jsdom;
const { window } = new JSDOM();
const { document } = (new JSDOM('')).window;
global.document = document;

var $ = jQuery = require('jquery')(window);

希望这对您或遇到此类问题的任何人有帮助。


TypeError: JSDOM is not a constructor
内森·霍克斯

如果您在Node端运行jQuery,首先,使用npm install安装jquery和jsdom。然后,在要尝试使用jquery选择器的文件中添加以上行。例如,我使用了$.each。我只添加了这些行,然后按如下所示进行操作: $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); 希望这会有所帮助!
Plabon Dutta

jsdom决定以某种方式根本不安装。我想我仍然在计算npm。谢谢@
内森·霍克斯,


0

这些解决方案都没有对我的Electron App有所帮助。

我的解决方案(解决方法):

npm install jquery

在您的index.js文件中:

var jQuery = $ = require('jquery');

通过.js以下方式在文件中编写您的jQuery函数:

jQuery(document).ready(function() {


-1

否。将浏览器环境移植到节点将是一项巨大的工作。

我正在研究单元测试的另一种方法是创建jQuery的“模拟”版本,该版本在调用选择器时提供回调。

这样,您就可以在没有DOM的情况下对jQuery插件进行单元测试。您仍然必须在真实的​​浏览器中进行测试,以查看代码是否可以正常运行,但是,如果您发现浏览器特定的问题,则也可以轻松地“模拟”单元测试中的问题。

准备好显示后,我将其推送到github.com/felixge。


我喜欢这个主意...应该很容易做到。
Sudhir Jonathan 2010年

-1

您可以使用Electron,它允许混合使用browserjs和nodejs。

以前,我尝试在nodejs中使用canvas2d,但最终我放弃了。默认情况下,nodejs不支持它,并且安装起来太困难了(很多... dependeces)。在使用Electron之前,我可以轻松地使用所有以前的browserjs代码,甚至是WebGL,并将结果值(例如,结果base64图像数据)传递给nodejs代码。


-9

从来没听说过。DOM是客户端的东西(jQuery不会解析HTML,而是DOM)。

以下是一些当前的Node.js项目:

https://github.com/ry/node/wikihttps://github.com/nodejs/node

而且SimonW的djangode非常酷...


我希望有可能。我已经尝试过将jquery包含在node.js项目中,但是当然没有用。jQuery基于文档/窗口。Rhino能够运行jQuery服务器端: ejohn.org/blog/bringing-the-browser-to-the-server 我要寻找更多的解析器。也许有一种不依赖于浏览器。
约翰

@John:jQuery可以在Rhino上运行的唯一原因是由于该项目:github.com/jeresig/env-js/blob/master/src/env.js 它模拟了DOM和JavaScript运行时的一小部分。它依赖于Java api,所以Node.js(使用V8 / C ++)是不可行的。

2
@Nosredna虽然您编写时可能确实如此,但显然不再正确了。我建议您现在删除答案。
基思·品森

-18

一种替代方法是使用Underscore.js。它应该提供您可能希望从JQuery的服务器端获得的东西。


10
你可以解释吗?jQuery提供了大量的DOM操作/遍历/过滤API。下划线看起来像与DOM无关的通用库实用程序。
Peter Lyons

1
同样在这里,我看不到这是如何相关的,两者是互补的,而不是替代的
Yi Jiang

2
这个答案不是完全错误的。jQuery和Underscore确实重叠:它们都提供诸如forEach之类的功能。
tuomassalo 2011年

8
-1它们具有重叠的功能,但是Underscore并不是jQuery的替代品。
山姆

2
问题是关于DOM操纵/选择器的问题。
mikermcneil
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.