Yêu cầu tại sao và khi nào sử dụng cấu hình shim


97

Tôi đã đọc tài liệu requestjs từ đây API

requirejs.config({
    shim: {
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore', 'jquery'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                //Using a function allows you to call noConflict for
                //libraries that support it, and do other cleanup.
                //However, plugins for those libraries may still want
                //a global. "this" for the function will be the global
                //object. The dependencies will be passed in as
                //function arguments. If this function returns a value,
                //then that value is used as the module export value
                //instead of the object found via the 'exports' string.
                return this.Foo.noConflict();
            }
        }
    }
});

nhưng tôi không nhận được shim phần của nó. tại sao tôi nên sử dụng shim và tôi nên cấu hình như thế nào, tôi có thể hiểu rõ hơn được không

Xin vui lòng bất kỳ ai có thể giải thích với ví dụ tại sao và khi nào chúng ta nên sử dụng miếng đệm. cảm ơn.

Câu trả lời:


110

Cách sử dụng chính của shim là với các thư viện không hỗ trợ AMD, nhưng bạn cần quản lý các phần phụ thuộc của chúng. Ví dụ, trong ví dụ về Backbone và Underscore ở trên: bạn biết rằng Backbone yêu cầu Underscore, vì vậy giả sử bạn đã viết mã của mình như thế này:

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequestJS sẽ khởi động các yêu cầu không đồng bộ cho cả Điểm dưới và Điểm chính, nhưng bạn không biết cái nào sẽ quay lại đầu tiên nên có thể Backbone sẽ cố gắng làm điều gì đó với Điểm dưới trước khi nó được tải.

LƯU Ý: ví dụ gạch dưới / xương sống này được viết trước khi cả hai thư viện đó hỗ trợ AMD. Nhưng nguyên tắc này đúng với bất kỳ thư viện nào ngày nay không hỗ trợ AMD.

Móc "init" cho phép bạn làm những việc nâng cao khác, ví dụ: nếu một thư viện thường xuất hai thứ khác nhau vào không gian tên chung nhưng bạn muốn xác định lại chúng trong một không gian tên duy nhất. Hoặc, có thể bạn muốn thực hiện một số bản vá lỗi trên các phương thức trong thư viện mà bạn đang tải.

Thêm nền:


Giống như mã ví dụ yout, UnderscoreBackbonehere sử dụng như bình thường, shimtrong trường hợp này phải làm gì? Tôi có thể sử dụng require( function() { _.extend({}); })? Nó có hiểu _không?
Stiger

"RequestJS sẽ khởi động các yêu cầu không đồng bộ cho cả Dấu gạch dưới và Đường trục" -> Có thể ngăn chặn điều này, trong trường hợp thư viện đã được tải?
Codii

1
@Codii đúng, nếu thư viện đã được tải, nó sẽ không khởi động một yêu cầu máy chủ khác, nhưng điểm của RequestJS là mã của bạn không cần quan tâm đến việc điều đó có xảy ra hay không. Có lẽ bắt đầu một câu hỏi mới cho trường hợp sử dụng cụ thể của bạn?
Explunit

63

Theo tài liệu API của RequestJS, shim cho phép bạn

Định cấu hình các phần phụ thuộc, xuất và khởi tạo tùy chỉnh cho các tập lệnh "toàn cầu trình duyệt" truyền thống, cũ hơn không sử dụng định nghĩa () để khai báo các phần phụ thuộc và đặt giá trị mô-đun.

- Cấu hình phụ thuộc

Giả sử bạn có 2 mô-đun javascript (mô-đunA và mô-đunB) và một trong số chúng (mô-đunA) phụ thuộc vào mô-đun kia (mô-đunB). Cả hai điều này đều cần thiết cho mô-đun của riêng bạn, vì vậy bạn chỉ định các phần phụ thuộc trong request () hoặc xác định ()

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

Nhưng vì bản thân yêu cầu cũng tuân theo AMD nên bạn không biết cái nào sẽ được tải sớm. Đây là nơi miếng đạn đến để giải cứu.

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

Điều này sẽ đảm bảo moduleB luôn được tải trước khi moduleA được tải.

- Định cấu hình xuất khẩu

Shim export cho RequestJS biết thành viên nào trên đối tượng toàn cục (tất nhiên là cửa sổ, giả sử bạn đang ở trong trình duyệt) là giá trị mô-đun thực tế. Giả sử moduleA tự thêm vào giá trị window'modA' (giống như jQuery và dấu gạch dưới tương ứng với $ và _), sau đó chúng tôi đặt giá trị xuất khẩu của chúng tôi là 'modA'.

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

Nó sẽ cung cấp cho RequestJS một tham chiếu cục bộ đến mô-đun này. ModA toàn cầu cũng sẽ tồn tại trên trang.

-Tùy chỉnh khởi tạo cho các tập lệnh "toàn cầu của trình duyệt" cũ hơn

Đây có lẽ là tính năng quan trọng nhất của cấu hình shim cho phép chúng tôi thêm các tập lệnh 'toàn cầu trình duyệt', 'không phải của AMD' (cũng không tuân theo mô-đun) làm phụ thuộc trong mô-đun của riêng chúng tôi.

Giả sử moduleB là javascript cũ đơn thuần chỉ có hai hàm funcA () và funcB ().

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

Mặc dù cả hai chức năng này đều có sẵn trong phạm vi cửa sổ, nhưng RequestJS khuyên chúng ta nên sử dụng chúng thông qua mã định danh / xử lý toàn cục của chúng để tránh nhầm lẫn. Vì vậy, định cấu hình miếng đệm như

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

Giá trị trả về từ hàm init được sử dụng làm giá trị xuất mô-đun thay vì đối tượng được tìm thấy thông qua chuỗi 'xuất'. Điều này sẽ cho phép chúng tôi sử dụng funcB trong mô-đun của riêng mình như

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

Hy vọng điều này sẽ giúp.


3
Dễ hiểu! Một câu hỏi: trong ví dụ cuối cùng, thuộc tính "xuất khẩu" có đơn giản bị bỏ qua không?
Niko Bellic

Không, nó không bị bỏ qua. Nếu thuộc tính "export" bị bỏ qua trong ví dụ trước, thì đối tượng bạn chuyển vào dưới dạng tham số ('B' trong trường hợp này) sẽ không được xác định vì moduleB KHÔNG tuân thủ AMD và sẽ không trả về một đối tượng để RequestJS sử dụng ( do đó 'B.funcB' sẽ không hoạt động).
nalinc

Hừ! Tôi nghĩ rằng giá trị của việc xuất sẽ bị ghi đè bởi đối tượng được trả về trong hàm init. Vì vậy, tham số B sẽ là đối tượng {funcA: funcA, funcB: funcB}, không đơn giản chỉ là funcB. Điều này có đúng không?
Niko Bellic

4
Niko Bellic nói đúng, IS bỏ qua xuất khẩu (tôi vừa mới kiểm tra điều đó). Đối tượng B là đối tượng được trả về bởi hàm được chỉ định trong phần 'init'. Nếu bạn loại bỏ phần 'init', đối tượng B sẽ trở thành hàm funcB, vì vậy bạn chỉ cần thực hiện B () thay vì B.funcB (). Và rõ ràng funcA sẽ không thể truy cập được trong trường hợp đó.
user4205580

-2

Bạn phải thêm đường dẫn trong requestjs.config để khai báo, ví dụ:

requirejs.config({
    paths: {
          'underscore' : '.../example/XX.js' // your JavaScript file
          'jquery' : '.../example/jquery.js' // your JavaScript file
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});

1
Câu trả lời này là một kết xuất mã mà không có gì để giải thích "tại sao và khi nào sử dụng cấu hình shim". Nếu bạn chỉnh sửa câu trả lời của mình để cung cấp lời giải thích, hãy đảm bảo rằng bạn đang thêm nội dung mới, điều đó chưa có trong các câu trả lời trước đó
Louis

copy dán mà không cần bất kỳ thông tin phản hồi tích cực
william.eyidi

phải là dấu phẩy trước miếng đệm:
Scott
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.