Làm cách nào để sử dụng requestJS và jQuery cùng nhau?


82

Tôi muốn sử dụng requestJS và tôi đang sử dụng jQuery. Tôi không muốn sử dụng phiên bản kết hợp của requestJS và jQuery vì tôi không sử dụng phiên bản jQuery mới nhất. Cách tốt nhất để tôi làm việc với RequestJS là gì?


2
Điều gì ngăn cản bạn sử dụng jQuery mới nhất?
Ẩn danh

Tôi đang sử dụng jQuery 1.3.8. Phiên bản này hoạt động hơi khác so với 1.4.X. Để sử dụng jQuery mới nhất, tôi phải cập nhật một số mã và ngay bây giờ tôi không có thời gian cho việc đó. Hơn nữa, tôi không nghĩ rằng việc kết hợp các gói là một điều đúng đắn.
Naor

Câu trả lời dưới đây rất hay ... tại sao bạn vẫn chưa đánh dấu là đúng?
Tù nhân ZERO

@Prisoner ZERO: Thành thật mà nói, tôi chưa quản lý để kiểm tra nó. đặc biệt là tôi đã sử dụng trình tải tập lệnh ajax của microsoft. Cảm ơn đã nhắc nhở tôi đánh dấu câu trả lời này. Nếu bạn nói điều đó thật tuyệt - tôi tin bạn.
Naor

Tôi cũng thấy các requestj khó sử dụng với các thư viện khác và ngược lại. Đó là lý do tại sao tôi tạo một thư viện dễ sử dụng hơn nhiều và được thử nghiệm với góc cạnh. Có một ứng dụng demo ở phía dưới: gngeorgiev.github.io/Modulerr.js Bạn cũng có thể kết hợp tất cả các kịch bản thành một mà không phụ thuộc vào Modulerr.js
Georgi-nó

Câu trả lời:


130

Đó cũng là câu hỏi chính xác của tôi! Tôi cũng phải sử dụng jQuery cũ hơn, nhưng cũng có nhiều thư viện javascript "truyền thống" hơn. Kỹ thuật tốt nhất để làm điều đó là gì? (Tôi có thể chỉnh sửa câu hỏi của bạn để làm cho nó rộng hơn nếu bạn không phiền.) Đây là những gì tôi học được.

Tác giả của RequestJS, James Burke, đã giải thích những ưu điểm của tệp RequestJS + jQuery kết hợp . Bạn nhận được hai điều.

  1. Một mô-đun, jquerycó sẵn, và đó là đối tượng jQuery. Điều này là an toàn:

    // My module depends on jQuery but what if $ was overwritten?
    define(["jquery"], function($) {
      // $ is guaranteed to be jQuery now */
    })
    
  2. jQuery đã được tải trước bất kỳ require()hoặc define()nội dung nào. Tất cả các mô-đun được đảm bảo rằng jQuery đã sẵn sàng. Bạn thậm chí không cần require/order.jsplugin vì jQuery về cơ bản đã được mã hóa cứng để tải trước.

Đối với tôi, số 2 không hữu ích lắm. Hầu hết các ứng dụng thực đều có nhiều .js tệp phải tải theo đúng thứ tự — thật đáng buồn nhưng đúng. Ngay khi bạn cần Sammy hoặc Underscore.js, tệp RequestJS + jQuery kết hợp không giúp được gì.

Giải pháp của tôi là viết các trình bao bọc RequestJS đơn giản để tải các tập lệnh truyền thống của tôi bằng cách sử dụng plugin "order".

Thí dụ

Giả sử ứng dụng của tôi có các thành phần này (theo phụ thuộc).

  • Ứng dụng của tôi, ứng dụng tuyệt vời
    • greatapp phụ thuộc vào jquery tùy chỉnh (phiên bản cũ tôi phải sử dụng)
    • greatapp phụ thuộc vào my_sammy (SammyJS cộng với tất cả các plugin của nó mà tôi phải sử dụng). Chúng phải theo thứ tự
      1. my_sammy phụ thuộc vào jquery (SammyJS là một plugin jQuery)
      2. my_sammy phụ thuộc vào sammy.js
      3. my_sammy phụ thuộc vào sammy.json.js
      4. my_sammy phụ thuộc vào sammy.storage.js
      5. my_sammy phụ thuộc vào sammy.mustache.js

Theo suy nghĩ của tôi, mọi thứ ở trên kết thúc bằng .jsmột kịch bản "truyền thống". Tất cả mọi thứ không có .jslà một plugin RequiJS. Điều quan trọng là: những thứ cấp cao (greatapp, my_sammy) là các mô-đun và ở các cấp độ sâu hơn, nó trở lại .jscác tệp truyền thống .

Khởi động

Tất cả bắt đầu bằng một phần mềm khởi động nói với RequestJS cách bắt đầu.

<html>
  <head>
    <script data-main="js/boot.js" src="js/require.js"></script>
  </head>
</html>

Trong js/boot.jstôi chỉ đặt cấu hình và cách khởi động ứng dụng.

require( // The "paths" maps module names to actual places to fetch the file.
         // I made modules with simple names (jquery, sammy) that will do the hard work.
         { paths: { jquery: "require_jquery"
                  , sammy : "require_sammy"
                  }
         }

         // Next is the root module to run, which depends on everything else.
       , [ "greatapp" ]

         // Finally, start my app in whatever way it uses.
       , function(greatapp) { greatapp.start(); }
       );

Ứng dụng chính

Trong greatapp.jstôi có một mô-đun trông bình thường.

define(["jquery", "sammy"], function($, Sammy) {
  // At this point, jQuery and SammyJS are loaded successfully.
  // By depending on "jquery", the "require_jquery.js" file will run; same for sammy.
  // Those require_* files also pass jQuery and Sammy to here, so no more globals!

  var start = function() {
    $(document).ready(function() {
      $("body").html("Hello world!");
    })
  }

  return {"start":start};
}

Yêu cầu trình bao bọc mô-đunJS xung quanh các tệp truyền thống

require_jquery.js:

define(["/custom/path/to/my/jquery.js?1.4.2"], function() {
  // Raw jQuery does not return anything, so return it explicitly here.
  return jQuery;
})

require_sammy.js:

// These must be in order, so use the "order!" plugin.
define([ "order!jquery"
       , "order!/path/to/custom/sammy/sammy-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.json-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.storage-0.6.2-min.js"
       , "order!/path/to/custom/sammy/plugins/sammy.mustache-0.6.2-min.js"
       ]

       , function($) {
           // Raw sammy does not return anything, so return it explicitly here.
           return $.sammy;
         }
      );

5
Làm tốt câu trả lời này ... hy vọng người hỏi sẽ đánh dấu điều này!
Tù nhân ZERO

bạn tạo một mô-đun request_jquery tùy thuộc vào tệp jquery thực tế, nhưng jquery không duy trì toàn cục? tệp jquery 1.4.2 thực tế mà bạn tải từ đường dẫn tùy chỉnh, không phải là mô-đun request.js? hay bạn cũng yêu cầu xung quanh tệp đó?
Sander

3
Tôi muốn lưu ý rằng với phiên bản mới nhất của jQuery (1.7), nó đã hỗ trợ các mô-đun và vì vậy tất cả những gì bạn cần làm là yêu cầu nó như bình thường và nó sẽ hoạt động.
MikeMurko

1
ai đó có thể cập nhật câu trả lời này để phản ánh cách thực hiện requestJS 2 (w / shim) + jQuery 1.7+ hỗ trợ AMD không?
Henry

1
Tôi chỉ muốn chỉ ra rằng cách tốt nhất để đạt được sự hỗ trợ phụ thuộc với các tệp javascript không phải của AMD là cấu hình shim được tìm thấy trong RequestJS 2.0+ Nếu bạn vẫn đang sử dụng Yêu cầu 1.x, bạn có thể sử dụng tiền thân của shim , wrapjs
Johann

32

Câu hỏi này hiện đã có ít nhất hai năm, nhưng tôi nhận thấy đây là một vấn đề vẫn còn xảy ra với RequestJS 2.0 (request-jquery.js sử dụng jQuery 1.8.0, nhưng phiên bản mới nhất là 1.8.2).

Nếu bạn tình cờ thấy câu hỏi này, hãy lưu ý rằng request-jquery.js bây giờ chỉ là request.js và jquery.js, được trộn với nhau. Bạn chỉ có thể chỉnh sửa request-jquery.js và thay thế các phần jQuery bằng một phiên bản mới hơn .

Cập nhật (ngày 30 tháng 5 năm 2013) : Hiện tại, RequiJS đã có đường dẫn và miếng đệm, có một cách mới để nhập các plugin jQuery và jQuery và phương pháp cũ không còn cần thiết nữa cũng không được khuyến khích . Đây là phiên bản rút gọn của phương thức hiện tại:

requirejs.config({
    "paths": {
      "jquery": "//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min"
    }
});

define(["jquery"], function($) {
    $(function() {
    });
});

Xem http://requirejs.org/docs/jquery.html để biết thêm thông tin.


Cảm ơn, điều này vẫn có liên quan :)
Naor

Bạn vẫn đang sử dụng jQuery 1.3.8? :)
Chris

Cảm ơn bạn đã chỉ ra điều này. Tôi đọc rằng phiên bản cũ hơn 1.8 có vấn đề đã được giải quyết trong phiên bản mới nhất.
Blaine Mucklow

Thật. Chúng không phải là vấn đề jQueryUI với curCSS, phải không?
Chris

1
@AHMED: Cả hai đều hoạt động. Sự khác biệt là xác định chỉ định rõ ràng một mô-đun. Tôi có xu hướng thích sử dụng xác định hầu như chỉ bởi vì nó rõ ràng hơn về con đường: stackoverflow.com/questions/16087635/...
Chris

9

Tôi đã tìm thấy cách tiếp cận tốt nhất là giữ jQuery bên ngoài bản dựng RequestJS của mình.

Chỉ cần bao gồm jquery.min.js trong HTML của bạn. Sau đó, tạo tệp jquery.js với một cái gì đó như thế này ...

define([], function() {
    return window.$;
});

Đây là một giải pháp tốt, vì tôi có một số tệp JS phải được tải theo cách truyền thống bằng cách sử dụng các thẻ script và chúng phụ thuộc vào jQuery.
Jingtao

3

Tìm thấy anwer của JasonSmith vô cùng hữu ích, có lẽ còn hơn cả tài liệu của RequestJS.

Tuy nhiên, có cách để tối ưu hóa nó để tránh có các yêu cầu AJAX riêng biệt cho các mô-đun khai báo xác định (nhỏ) ("request_jquery" "request_sammy"). Tôi nghi ngờ r.js sẽ làm điều đó ở giai đoạn tối ưu hóa, nhưng bạn có thể làm điều đó trước thời hạn để không chiến đấu với hệ thống Path, BaseURI.

index.html:

<html>
  <head>
    <script data-main="js/loader.js" src="js/require.js"></script>
  </head>
</html>

loader.js:

// We are going to define( dependencies by hand, inline.
// There is one problem with that through (inferred from testing):
// Dependencies are starting to load (and execute) at the point of declaring the inline
// define, not at the point of require(
// So you may want to nest the inline-defines inside require( 
// this is, in a way, short replacement for Order plug in, but allows you to use
// hand-rolled defines, which the Order plug in, apparently does not allow.

var jQueryAndShims = ['jquery']

if(window.JSON == null){
    jQueryAndShims.push('json2')
    define(
        'json2'
        , ['js/libs/json2.min.js']
        , function() {
            return window.JSON
        }
    )
}
// will start loading the second we define it.
define(
    'jquery'
    , ['js/libs/jquery_custom.min.js']
    , function() {
        // we just pick up global jQuery here. 
        // If you want more than one version of jQuery in dom, read a more complicated solution discussed in
        // "Registering jQuery As An Async-compatible Module" chapter of
        // http://addyosmani.com/writing-modular-js/
        return window.jQuery 
    }
)

// all inline defines for resources that don't rely on other resources can go here.

// First level require(
// regardless of depends nesting in 'myapp' they will all start downloading 
// at the point of define( and exec whenever they want, 
// async in many browsers. Actually requiring it before the nested require makes
// sure jquery had *executed and added jQuery to window object* before
// all resolved depends (jquery plugins) start firing.
require(jQueryAndShims, function($) {

    // will start loading the second we define it.        
    define(
        'sammy_and_friends'
        , ['jquery','js/libs/jquery_pluginone.min.js','js/libs/jquery_plugintwo.min.js','js/libs/sammy.min.js']
        , function($) {
            // note, all plugins are unaltered, as they are shipped by developers.
            // in other words, they don't have define(.. inside.
            // since they augment global $ (window.jQuery) anyway, and 'jquery' define above picks it up
            // , we just keep on returning it.
            // Sammy is attached to $ as $.sammy, so returning just Sammy makes little sense
            return $
        }
    )

    // second level require - insures that Sammy (and other jQuery plugins) - 'sammy_and_friends' - is
    // loaded before we load Sammy plugins. I normally i would inline all sammy plugins i need 
    // (none, since i use none of them preferring jQuery's direct templating API
    // and no other Sammy plug in is really of value. )  right into sammy.js file. 
    // But if you want to keep them separate:
    require(['sammy_and_friends'], function() {

        // will start loading the second we define it.
        define(
            'sammy_extended'
            , ['sammy_and_friends','js/libs/sammy_pluginone.min.js','js/libs/sammy_plugintwo.min.js']
            , function($) {
                // as defined above, 'sammy_and_friends' actually returns (globall) jQuery obj to which
                // Sammy is attached.  So we continue to return $
                return $
            }
        )
        // will start loading the second we define it.
        define(
            'myapp'
            , ['sammy_extended', 'js/myapplication_v20111231.js'] 
            , function($, myapp_instantiator) {
                // note, myapplication may, but does not have to contain RequireJS-compatible define
                // that returns something. However, if it contains something like 
                // "$(document).ready(function() { ... " already it MAY fire before 
                // it's depends - 'sammy_extended' is fully loaded.
                // Insdead i recommend that myapplication.js returns a generator 
                // (app-object-generating function pointer)
                // that takes jQuery (with all loaded , applied plugins) 
                // The expectation is that before the below return is executed, 
                // all depends are loaded (in order of depends tree)
                // You would init your app here like so:
                return myapp_instantiator($)
                // then "Run" the instance in require( as shown below
            }
        )

        // Third level require - the one that actually starts our application and relies on
        // dependency pyramid stat starts with jQuery + Shims, followed by jQuery plugins, Sammy, 
        // followed by Sammy's plugins all coming in under 'sammy_extended'
        require(['jquery', 'myapp'], function($, myappinstance) {
            $(document).ready(function() {myappinstance.Run()})
        })
    }) // end of Second-level require
}) // end of First-level require

cuối cùng, myapplication.js:

// this define is a double-wrap.
// it returns application object instantiator that takes in jQuery (when it's available) and , then, that
// instance can be "ran" by pulling .Run() method on it.
define(function() {
    // this function does only two things:
    // 1. defines our application class 
    // 2. inits the class and returns it.
    return function($) {
        // 1. defining the class
        var MyAppClass = function($) {
            var me = this
            this._sammy_application = $.sammy(function() {
                this.raise_errors = true
                this.debug = true
                this.run_interval_every = 300
                this.template_engine = null
                this.element_selector = 'body'
                // ..
            })
            this._sammy_application.route(...) // define your routes ets...
            this.MyAppMethodA = function(blah){log(blah)}  // extend your app with methods if you want
            // ...
             // this one is the one we will .Run from require( in loader.js
            this.Run = function() {
                me._sammy_application.run('#/')
            }
        }
        // 2. returning class's instance
        return new MyAppClass($) // notice that this is INITED app, but not started (by .Run) 
        // .Run will be pulled by calling code when appropriate
    }
})

Cấu trúc này (thay thế một cách lỏng lẻo (trùng lặp?) Plugin Đặt hàng của RequestJS, nhưng) cho phép bạn cắt bớt số lượng tệp bạn cần để AJAX, thêm nhiều quyền kiểm soát hơn đối với định nghĩa của cây phụ thuộc và phụ thuộc.

Ngoài ra còn có một phần thưởng lớn khi tải jQuery riêng (thường có giá 100k) - bạn có thể kiểm soát bộ nhớ đệm tại máy chủ hoặc lưu trữ jQuery vào bộ nhớ đệm của trình duyệt. Hãy xem dự án AMD-Cache tại đây https://github.com/jensarps/AMD-cache sau đó thay đổi định nghĩa (câu lệnh để bao gồm "cache!": Và nó sẽ bị kẹt (mãi mãi :)) trong trình duyệt của người dùng.

define(
    'jquery'
    , ['cache!js/libs/jquery_old.min.js']
    , function() {
        // we just pick up global jQuery here. 
        // If you want more than one version of jQuery in dom, read a more complicated solution discussed in
        // "Registering jQuery As An Async-compatible Module" chapter of
        // http://addyosmani.com/writing-modular-js/
        return window.jQuery 
    }
)

Lưu ý về jQuery 1.7.x + Nó không còn tự gắn vào đối tượng window, vì vậy điều trên sẽ KHÔNG hoạt động với tệp jQuery 1.7.x + chưa sửa đổi. Ở đó, bạn phải tùy chỉnh jquery **. Js của mình để bao gồm cái này trước khi đóng "}) (window);":

;window.jQuery=window.$=jQuery

Nếu bạn gặp lỗi "jQuery undefined" trong bảng điều khiển, đó là dấu hiệu phiên bản jQuery bạn đang sử dụng không tự gắn vào window.

Giấy phép mã: Miền công cộng.

Tiết lộ: JavaScript ở trên có mùi "mã giả" vì nó là cách diễn giải (cắt tỉa bằng tay) của mã sản xuất chi tiết hơn nhiều. Mã như được trình bày ở trên không được đảm bảo hoạt động và KHÔNG được kiểm tra để hoạt động như đã trình bày. Kiểm tra, kiểm tra nó. Mục đích bỏ qua dấu chấm phẩy vì chúng không bắt buộc theo thông số JS và mã trông đẹp hơn nếu không có chúng.


Sau khi chiến đấu với RequestJS (mọi thứ tải không theo thứ tự, không tôn trọng xác định, yêu cầu làm tổ. Những hành vi sai trái phép thuật khác) chuyển sang Curl.JS và bắt đầu ngủ ngon vào ban đêm. Nó không phải là cường điệu, nhưng, chết tiệt, nó ổn định và dễ sử dụng!
ddotsenko

1

Ngoài câu trả lời của jhs, hãy xem hướng dẫn mới hơn trên trang github request-jquery từ tệp README.md. Nó bao gồm cả cách tiếp cận đơn giản nhất của việc sử dụng tệp jquery / Requi.js kết hợp và cả cách sử dụng một tệp jquery.js riêng biệt.

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.