Tôi có thể sử dụng jQuery với Node.js không?


574

Có thể sử dụng các bộ chọn / thao tác DOM trên phía máy chủ bằng Node.js không?


3
Tôi tự hỏi: Tại sao sử dụng ở phía máy chủ trong khi bạn có thể làm điều đó ở phía máy khách?
Inanc Gumus

31
Có lẽ bạn có thể muốn tạo một chương trình quét web để loại bỏ thông tin cụ thể theo định kỳ và lưu trữ kết quả trong cơ sở dữ liệu? Điều này sẽ không thực tế từ phía khách hàng.
Trevor

2
Bạn cũng nên xem ph Phantomjs, cho phép bạn mô phỏng phía máy chủ trình duyệt với động cơ V8.
Dimitri Kopriwa

2
Thao tác @deeperx DOM ở phía máy chủ có thể hữu ích khi tạo trình thu thập thông tin. Xem câu trả lời này .
Lucio Paiva

CÓ - hãy xem câu trả lời này - Tôi thích điều này hơn là sử dụng cổ vũ, vì bạn có toàn bộ sức mạnh của bộ chọn jQuery.
monika mevenkamp

Câu trả lời:


563

Cập nhật (27-ngày 18 tháng 6) : Có vẻ như đã có một bản cập nhật lớn jsdomkhiến câu trả lời ban đầu không còn hoạt động. Tôi tìm thấy câu trả lời này giải thích làm thế nào để sử dụng jsdombây giờ. Tôi đã sao chép mã có liên quan dưới đây.

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

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

Lưu ý: Câu trả lời ban đầu không đề cập đến là bạn sẽ cần phải cài đặt jsdom bằng cách sử dụngnpm install jsdom

Cập nhật (cuối năm 2013) : Đội jQuery chính thức cuối cùng đã tiếp quản việc quản lý các jquerygói trên NPM:

npm install jquery

Sau đó:

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


43
Có thể sử dụng jQuery ajax từ node.js với mô đun npm đó không?
ajsie

22
Không cài đặt trên Windows (không công việc quan trọng ), trong trường hợp đó tôi sẽ đề xuất mô-đun Cheerio: matthewmueller.github.com/cheerio
Simon East

7
+1 để hiển thị nơi nhận npm :) hầu hết mọi người có thói quen xấu là chỉ đề cập đến công cụ như thể đó là một điều nhất định (lẽ thường)
Val

12
Điều này trở lại require("...").env is not a function.
Banderi

4
@Banderi cùng với tôi, có ý kiến ​​gì không? lỗi:TypeError: require(...).env is not a function
coderInrRain

58

Có, bạn có thể, sử dụng một thư viện mà tôi đã tạo được gọi là 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
Lưu ý rằng nodeQuery thực sự đang thay đổi trang của người dùng theo thời gian thực, do đó, nó thậm chí còn tuyệt vời hơn người ta tưởng.
alessioalex

Tôi đã tìm kiếm một cái gì đó như thế này khi tôi tình cờ ở đây ... Tôi vừa xem các gói nút nQuery và jquery và nQuery đã được cập nhật một năm trước, nơi jquery là ngày hôm qua ... Có phải nQuery không còn được phát triển? và jquery có ảnh hưởng đến phía máy khách như nQuery không? Có ai đã thử cả hai có lẽ?
Logan

2
@Logan nQuery về cơ bản chỉ là jquery. sự khác biệt là mã được chạy trên máy chủ và thay vì cung cấp mã jquery cho trình duyệt, nó chạy mã trên máy chủ và thực hiện thao tác dom cho các trình duyệt được kết nối từ xa. Cũng lưu ý rằng nQuery là một dự án thử nghiệm, và trong khi tôi sẽ chấp nhận yêu cầu kéo để sửa các lỗi, nó không bao giờ được tạo ra cho bất cứ mục đích hoặc dự án cụ thể vì vậy nó đã không có nhiều cam kết
Thomas Blobaum

@ThomasBlobaum không hoạt động cho tôi, lỗi: , express = Express.createServer();TypeError: Express.createServer is not a functioný tưởng nào?
coderInrRain

@ThomasBlobaum có vẻ như bạn chưa có phiên bản Express mới nhất. Hãy thử npm install --save expresstrong dấu nhắc lệnh của bạn.
gilbert-v

55

Tại thời điểm viết cũng có Cheerio duy trì .

Việc triển khai nhanh chóng, linh hoạt và tinh gọn của jQuery lõi được thiết kế dành riêng cho máy chủ.


2
+1 cho Cheerio. jsdom, mặt khác, thực sự đau đớn để có được chạy trên Windows.
Simon East

1
Cheerio có thể sử dụng các sự kiện bị trì hoãn và các cuộc gọi ajax không?
Hoffmann

6
không hỗ trợ nhiều công cụ chọn như:gt(1)
chovy

1
Theo kinh nghiệm của tôi, cái này hoạt động tốt nhất. Nó nhanh hơn JSDOM rất nhiều.
Jason Prawn

1
@Hoffmann, tôi đã dành một giây để kiểm tra tài liệu cho bạn. Không nó không. Cheerio chỉ có các phương thức liên quan đến DOM.
Denis

39

Sử dụng jsdom bây giờ bạn có thể. Chỉ cần nhìn vào ví dụ jquery của họ trong thư mục ví dụ.


một mặt trái của jQuerys () của jsdom là nó chạy tất cả các tập lệnh của trang.
thu hút

và nó không hoạt động trên Windows mà không phải đau đầu
Jason Goemaat

1
vào năm 2016 bạn không cần jsdom nữa - hãy xem câu trả lời của tôi: stackoverflow.com/a/40656811/3391783
low_rents

34

Một bánh xích đơn giản sử dụng Cheerio

Đây là công thức của tôi để tạo một trình thu thập thông tin đơn giản trong Node.js. Đó là lý do chính cho việc muốn thực hiện thao tác DOM ở phía máy chủ và có lẽ đó là lý do tại sao bạn đến đây.

Đầu tiên, sử dụng requestđể tải xuống trang được phân tích cú pháp. Khi quá trình tải xuống hoàn tất, hãy xử lý nó cheeriovà bắt đầu thao tác DOM giống như sử dụng jQuery.

Ví dụ làm việc:

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

Ví dụ này sẽ in ra bàn điều khiển tất cả các câu hỏi hàng đầu hiển thị trên trang chủ SO. Đây là lý do tại sao tôi yêu Node.js và cộng đồng của nó. Nó không thể dễ dàng hơn thế :-)

Cài đặt phụ thuộc:

npm cài đặt yêu cầu cổ vũ

Và chạy (giả sử tập lệnh ở trên có trong tệp crawler.js):

nút crawler.js


Mã hóa

Một số trang sẽ có nội dung không phải tiếng Anh trong một mã hóa nhất định và bạn sẽ cần giải mã nó UTF-8. Ví dụ, một trang bằng tiếng Bồ Đào Nha của Brazil (hoặc bất kỳ ngôn ngữ nào khác có nguồn gốc Latin) có thể sẽ được mã hóa bằng ISO-8859-1(còn gọi là "latin1"). Khi cần giải mã, tôi bảo requestkhông diễn giải nội dung theo bất kỳ cách nào và thay vào đó sử dụng iconv-liteđể thực hiện công việc.

Ví dụ làm việc:

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

Trước khi chạy, cài đặt phụ thuộc:

npm cài đặt yêu cầu iconv-lite cổ vũ

Và cuối cùng:

nút crawler.js


Theo liên kết sau

Bước tiếp theo sẽ là theo liên kết. Giả sử bạn muốn liệt kê tất cả các áp phích từ mỗi câu hỏi hàng đầu trên SO. Trước tiên, bạn phải liệt kê tất cả các câu hỏi hàng đầu (ví dụ ở trên) và sau đó nhập từng liên kết, phân tích từng trang của câu hỏi để có danh sách người dùng liên quan.

Khi bạn bắt đầu theo các liên kết, một địa ngục gọi lại có thể bắt đầu. Để tránh điều đó, bạn nên sử dụng một số loại lời hứa, tương lai hoặc bất cứ điều gì. Tôi luôn giữ async trong toolbelt của mình. Vì vậy, đây là một ví dụ đầy đủ về trình thu thập thông tin bằng cách sử dụng async:

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

Trước khi chạy:

npm cài đặt yêu cầu async cổ vũ

Chạy thử nghiệm:

nút crawler.js

Đầu ra mẫu:

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

Và đó là điều cơ bản bạn nên biết để bắt đầu tạo trình thu thập thông tin của riêng mình :-)


Thư viện sử dụng


22

năm 2016 mọi thứ dễ dàng hơn cài đặt jquery cho node.js bằng bàn điều khiển của bạn:

npm install jquery

liên kết nó với biến $(ví dụ - tôi đã quen với nó) trong mã node.js của bạn:

var $ = require("jquery");

làm công cụ:

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

cũng hoạt động cho gulp vì nó dựa trên node.js.


Phiên bản nào của nút bạn đang sử dụng? Trên Mac, Node 6.10.2, jquery 2.2.4, var $ = require("jquery"); $.ajax // undefined (Downvote cho thời điểm này).
AJP

@AJP và bạn có chắc là bạn đã làm npm install jquerytrước?
low_rents

1
Đúng. > console.log(require("jquery").toString());cung cấp cho tôi chức năng của nhà máy: function ( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); } Tôi đã phải sử dụng câu trả lời ở trên với jsdom: stackoverflow.com/a/4129032/539490
AJP

@AJP ok, thật lạ.
low_rents

Tôi nhận được chính xác chức năng nhà máy giống như @AJP. Phiên bản jquery nào bạn đã sử dụng, @low_rents?
Boris Burkov

18

Tôi tin rằng câu trả lời cho điều này bây giờ là có.
https://github.com/tmpvar/jsdom

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

9
Tôi rất tiếc phải báo cáo rằng sẽ mất nhiều công sức hơn để chạy jQuery trên jsdom. Sizzle tuy nhiên không hoạt động! Tôi thực sự muốn giữ jsdom càng nhẹ càng tốt, vì vậy việc thêm vào trình giả lập trình duyệt đầy đủ như env.js không thực sự là ưu tiên tại thời điểm này.
tmpvar

không sao, tôi tìm thấy bản sao đã sửa đổi đi kèm với jsdom.
lôi cuốn

Bây giờ, nút-jquery của FYI không được dùng nữa để ủng hộ jquery
Ruslan López

1
ReferenceError: cửa sổ không được xác định
Bon

17

npm install jquery --save #note TẤT CẢ CÁC LOWERCASE

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

đây là câu trả lời gọn gàng! vui lòng upvote này
datdinhquoc

8

Mô-đun jQuery có thể được cài đặt bằng cách sử dụng:

npm install jquery

Thí dụ:

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

Các tham chiếu của jQuery trong Node.js **:


2
Không hoạt động đối với tôi ... C: \ ... \ node_modules \ jquery \ dist \ jquery.js: 31 ném Lỗi mới ("jQuery yêu cầu một cửa sổ có tài liệu"); ^ Lỗi: jQuery yêu cầu một cửa sổ có tài liệu tại module.exports (C: \ ... \ WebContent \ resource \ js \ node_modules \ jquery \ dist \ jquery.js: 31: 12)
Jose Manuel Gomez Alvarez

var jsdom = Yêu cầu ("jsdom"); cửa sổ var = jsdom.jsdom (). defaultView; jsdom.jQueryify (window, " code.jquery.com/jquery.js ", function () {var $ = window. $; $ ("body"). preend ("<h1> Tiêu đề </ h1>") ; console.log ($ ("h1"). html ());});
SUNDARRAJAN K

7

Bạn phải lấy cửa sổ bằng API JSDOM mới.

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

.JSDOM ( ...) phải là .JSDOM ("<! DOCTYPE html>") để hỗ trợ HTML5?
datdinhquoc

2

CẢNH BÁO

Giải pháp này, như được đề cập bởi Golo Roden là không chính xác . Đây chỉ là một sửa chữa nhanh để giúp mọi người chạy mã jQuery thực tế của họ bằng cách sử dụng cấu trúc ứng dụng Node, nhưng đó không phải là triết lý của Node vì jQuery vẫn chạy ở phía máy khách thay vì ở phía máy chủ. Tôi xin lỗi vì đã trả lời sai.


Bạn cũng có thể kết xuất Jade với nút và đặt mã jQuery của bạn vào trong. Đây là mã của tập tin ngọc bích:

!!! 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
Bị từ chối vì câu hỏi tuyên bố rõ ràng rằng đó là về jQuery ở phía máy chủ. Bằng cách đơn giản nhúng jQuery vào tệp ngọc, jQuery vẫn chạy ở phía máy khách. Do đó, câu trả lời này không giúp ích gì: - /
Golo Roden

2
OK cảm ơn bạn rất nhiều. Tôi đã hiểu nó Tôi sẽ cố gắng làm rõ nó trong câu trả lời để không nhầm lẫn những người đọc nó. Cảm ơn một lần nữa vì sự giúp đỡ của bạn Golo.
Timbergus

2
Không có gì :-). Và đừng bận tâm: Tất cả chúng ta đều mắc lỗi, vì vậy đừng lo lắng :-)
Golo Roden

2

Mã làm việc của tôi là:

npm install jquery

và sau đó:

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

hoặc nếu cửa sổ có mặt, thì:

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

1

Các mô-đun jsdom là một công cụ tuyệt vời. Nhưng nếu bạn muốn đánh giá toàn bộ trang và thực hiện một số nội dung thú vị ở phía máy chủ, tôi khuyên bạn nên chạy chúng trong ngữ cảnh của riêng mình:

vm.runInContext

Vì vậy, những thứ như require/ CommonJStrên trang web sẽ không thổi quá trình Node của bạn.

Bạn có thể tìm tài liệu ở đây . Chúc mừng!


1

Kể từ jsdom v10, hàm .env () không được dùng nữa. Tôi đã làm như dưới đây sau khi thử rất nhiều thứ để yêu cầu 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);

Hy vọng điều này sẽ giúp bạn hoặc bất cứ ai đã và đang phải đối mặt với các loại vấn đề này.


TypeError: JSDOM is not a constructor
Nathan Hawks

Nếu bạn đang chạy jQuery ở phía Node, trước tiên, hãy cài đặt jquery và jsdom bằng cách sử dụng cài đặt npm. Sau đó, thêm các dòng trên vào tệp bạn đang cố sử dụng bộ chọn jquery. Ví dụ: tôi đã sử dụng a $.each. Tôi chỉ bao gồm những dòng này và sau đó đã làm như dưới đây: $.each(errors, function (ind,error) { res.send(error.msg);console.log(error.msg); }); Hy vọng điều này sẽ giúp !!
Plabon Dutta

Bằng cách nào đó jsdom đã quyết định không cài đặt gì cả. Tôi đoán tôi vẫn đang tìm ra npm. Cảm ơn @
Nathan Hawks


0

Không có giải pháp nào trong số này giúp tôi trong Ứng dụng điện tử.

Giải pháp của tôi (cách giải quyết):

npm install jquery

Trong index.jstập tin của bạn :

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

Trong các .jstệp của bạn, hãy viết các hàm jQuery của bạn theo cách này:

jQuery(document).ready(function() {


-1

Không. Sẽ là một nỗ lực khá lớn để chuyển môi trường trình duyệt sang nút.

Một cách tiếp cận khác, hiện tôi đang nghiên cứu để thử nghiệm đơn vị, là tạo phiên bản "Mock" của jQuery cung cấp các cuộc gọi lại bất cứ khi nào một bộ chọn được gọi.

Bằng cách này, bạn có thể đơn vị kiểm tra các trình cắm jQuery của mình mà không cần có DOM. Bạn vẫn sẽ phải kiểm tra trong các trình duyệt thực để xem mã của bạn có hoạt động không, nhưng nếu bạn phát hiện ra các sự cố cụ thể của trình duyệt, bạn cũng có thể dễ dàng "chế nhạo" những người trong bài kiểm tra đơn vị của mình.

Tôi sẽ đẩy thứ gì đó lên github.com/felixge khi nó sẵn sàng hiển thị.


Tôi thích ý tưởng này ... nó sẽ khá dễ thực hiện.
Sudhir Jonathan

-1

Bạn có thể sử dụng Electron , nó cho phép hybridj trình duyệt và nodejs.

Trước đây, tôi đã thử sử dụng canvas2d trong nodejs, nhưng cuối cùng tôi đã từ bỏ. Nó không được hỗ trợ bởi nodejs mặc định và quá khó để cài đặt nó (nhiều ... phụ thuộc). Cho đến khi tôi sử dụng Electron, tôi có thể dễ dàng sử dụng tất cả mã trình duyệt trước đó, thậm chí WebGL và chuyển giá trị kết quả (ví dụ: dữ liệu hình ảnh base64) cho mã nodejs.


-9

Không phải là tôi biết. DOM là một thứ phía máy khách (jQuery không phân tích cú pháp HTML, nhưng DOM).

Dưới đây là một số dự án Node.js hiện tại:

https://github.com/ry/node/wiki ( https://github.com/nodejs/node )

Và djangode của SimonW khá tuyệt ...


Tôi ước nó có thể. Tôi đã thử bao gồm jquery trên một dự án node.js và tất nhiên nó không hoạt động. jQuery dựa trên tài liệu / cửa sổ. Rhino có khả năng chạy phía máy chủ jQuery: ejohn.org/blog/browing-the-browser-to-the-server Tôi sẽ tìm kiếm nhiều trình phân tích cú pháp hơn. Có lẽ có một cái không phụ thuộc vào trình duyệt.
Giăng

@ John: lý do duy nhất mà jQuery có thể chạy trên Rhino là vì dự án này: github.com/jeresig/env-js/blob/master/src/env.js Nó mô phỏng một phần nhỏ của DOM và thời gian chạy JavaScript. Nó phụ thuộc vào apis Java vì vậy không có lợi cho Node.js (sử dụng V8 / C ++).
Lưỡi liềm tươi

2
@Nosredna Mặc dù điều này có thể đúng khi bạn viết nó, nhưng rõ ràng nó không còn đúng nữa. Tôi đề nghị bạn xóa câu trả lời của bạn bây giờ.
Keith Pinson

-18

Một cách khác là sử dụng Underscore.js . Nó sẽ cung cấp những gì bạn có thể muốn phía máy chủ từ JQuery.


10
Bạn có thể giải thích? jQuery cung cấp hàng tấn API thao tác / duyệt / lọc DOM. Gạch dưới trông giống như các tiện ích thư viện chung không liên quan gì đến DOM.
Peter Lyons

1
Tương tự ở đây, tôi không thấy điều này có liên quan như thế nào cả hai là bổ sung, không phải là lựa chọn thay thế
Yi Jiang

2
Câu trả lời này không hoàn toàn sai. jQuery và Underscore thực hiện chồng chéo: cả hai đều cung cấp các tính năng như forEach.
tuomassalo

8
-1 Chúng có chức năng chồng lấp nhưng Underscore không phải là một thay thế jQuery.
Sam

2
Câu hỏi là hỏi về thao tác / bộ chọn DOM mặc dù.
mikermcneil
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.