2012-02-15 27 views
26

Tôi khá mới đối với RequireJS và tôi đã gặp phải một chút vấn đề. Tôi đã viết một khung công tác nhỏ được xây dựng trên Backbone bằng cách sử dụng RequireJS và tôi muốn nó có thể sử dụng lại được trong các dự án khác nhau. Vì vậy, với một số tìm kiếm tôi đã học được rằng yêu cầu cho phép các gói. Điều này có vẻ như những gì tôi đang tìm kiếm. Tôi có một tập tin main.js để khởi động ứng dụng của tôi mà về cơ bản trông như thế này:Đường dẫn tương đối với mô-đun/gói RequireJS

require.config({ 
    packages: ['framework'] 
}); 

require(['framework'], function(framework) { 
    framework.createDash(); 
}); 

Sau đó, trong cùng thư mục với main.js của tôi, tôi đã một thư mục gọi là "khuôn khổ", trong đó có một main.js trông như thế này:

define(function(require, exports, module) { 
    exports.createDash = function(dash, element) { 
    require(['dash/dash.model', 'dash/dash.view'], function(DashModel, DashView) { 
     return new DashView({ 
     model: new DashModel(dash), 
     el: element ? element : window 
     }); 
    }); 
    }; 
}); 

Trong tìm kiếm tôi thấy this page mà chỉ ra rằng các 'đòi hỏi' tranh luận nên được scoped đến submodule. Tuy nhiên, khi tôi cố gắng yêu cầu mọi thứ, chúng vẫn còn liên quan đến main.js. gốc của tôi Tôi đã thử một số thứ và tìm kiếm hàng giờ để không có kết quả. Có cách nào tôi có thể có yêu cầu của tôi/xác định các cuộc gọi trong gói của tôi bao gồm liên quan đến main.js trong gốc của nó?

Trả lời

50

Bạn cần phải xác định submodule của bạn như gói trong cấu hình yêu cầu:

require.config({ 
    packages: [ 
    { name: 'packagename', 
     location: 'path/to/your/package/root', // default 'packagename' 
     main: 'scriptfileToLoad'    // default 'main' 
    }] 
    ... some other stuff ... 
}); 

Để tải mô-đun của bạn, bạn chỉ cần sử dụng 'tên gói' tại các yêu cầu:

define(['jquery', 'packagename'], function($, MyPackage) { 
    MyPackage.useIt() 
}); 

Trong của bạn gói bạn phải sử dụng tiền tố ./ để tải các tệp của bạn liên quan đến mô-đun con của bạn:

define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) { 
    LocalFile.finallyLoaded(); 
}); 

Có một phím tắt hữu ích: Nếu tên gói của bạn tương đương với vị trí của bạn và tập tin chính của bạn được gọi là 'main.js', sau đó bạn có thể thay thế này

packages: [ 
    { name: 'packagename', 
     location: 'packagename', 
     main: 'main' 
    }] 

này:

packages: ['packagename'] 

Theo như tôi thấy, bạn đã cố xác định gói nhưng bạn cũng sử dụng tiền tố ./? Nếu không có tiền tố này yêu cầu sẽ cố gắng tìm các tập tin trong đường dẫn gốc toàn cầu của nó. Và không có gói, ./ sẽ vô ích vì đường dẫn tương đối giống với đường dẫn gốc chung.


Cheers

+3

Điều này vẫn cho phép gói để thực hiện cuộc gọi riêng biệt của nó tới require.config() và xác định danh sách riêng biệt của bí danh đường dẫn, miễn là các tệp tham chiếu bí danh bắt đầu bằng './'? Tôi không muốn phải sử dụng đường dẫn tương đối đầy đủ cho tất cả các tệp, mỗi khi tôi tham chiếu chúng với một hàm define(). Tôi đã kể từ khi tái cấu trúc toàn bộ dự án, nhưng tôi vẫn tò mò. –

+0

Tôi biết câu trả lời này là một chút ngày, nhưng gần đây, bạn có thể sử dụng một cách an toàn đường dẫn tương đối để yêu cầu các mô-đun ngay cả khi không có gói. – hayavuk

+0

Để tham khảo: http://requirejs.org/docs/api.html#packages – Skarllot

2

này làm việc cho tôi, thêm một tiền tố "./" với tên mô-đun:

define(function (require, exports, module) { 
    exports.createDash = function (dash, element) { 
     require([ './dash/dash.model', './dash/dash.view' ], function (DashModel, DashView) { 
      return new DashView({ 
       model : new DashModel(dash), 
       el : element ? element : window 
      }); 
     }); 
    }; 
}); 
+0

Cảm ơn bạn đã trả lời. './' đã làm việc để tải hai thành phần này, nhưng tôi đoán tôi đã không làm tốt công việc giải thích câu hỏi (chủ yếu là do tôi không nghĩ mình đã hiểu đầy đủ câu hỏi tại thời điểm tôi đăng) . Thực sự vấn đề của tôi đã đi xuống, làm thế nào để tôi xác định đường dẫn với require.config() có thể được sử dụng từ cả hai bên trong bối cảnh khung công tác và không có, nhưng vẫn bao gồm cùng một tệp? Có thể có một giải pháp tốt hơn ngoài đó cho những gì tôi đang cố gắng làm, nhưng ít nhất tôi có một cái gì đó làm việc ngay bây giờ. Cảm ơn một lần nữa! –

5

tôi đã tìm ra câu trả lời cho câu hỏi của tôi, và các giải pháp (họ không giống nhau rõ ràng). Tôi đoán tôi sẽ đăng nó ở đây trong trường hợp nó có thể giúp đỡ người khác trong tương lai.

Về cơ bản những gì tôi muốn là tải khung của tôi trong bối cảnh riêng của mình. Tôi đã tìm thấy tùy chọn ngữ cảnh theo số configuration section trên trang web của yêu cầu và example of how to use it. Ban đầu tôi đã thử điều này bằng cách thực hiện một số việc như:

var req = require.config({ 
    baseUrl: 'framework', 
    context: 'framework', 

    paths: { 
     jQuery: 'lib/jquery/jquery-1.7.min.js', 
     Underscore: 'lib/underscore/underscore.min.js', 
     Backbone: 'lib/backbone/backbone.min.js', 
     etc... 
    } 
}); 

req(['main'], function() {}); 

Có hai vấn đề với điều này. Đầu tiên, biến 'req' của tôi đã được định nghĩa bên ngoài khung công tác, nhưng tôi muốn khung công tác định nghĩa các đường dẫn riêng của nó. Và thứ hai, bất cứ khi nào một tệp bên ngoài khung công tác sẽ yêu cầu một tệp trong khung công tác, điều này sẽ yêu cầu 'jQuery', ví dụ, sau đó jQuery (hoặc bất kỳ thứ gì khác) sẽ không được yêu cầu từ bên trong ngữ cảnh của cá thể khung công tác yêu cầu và do đó không thể tìm thấy tệp.

Những gì tôi đã kết thúc làm được xác định main.js khuôn khổ của tôi để tìm một cái gì đó như thế này:

var paths = { 
    jQuery: 'lib/jquery/jquery-1.7.min.js', 
    Underscore: 'lib/underscore/underscore.min.js', 
    Backbone: 'lib/backbone/backbone.min.js', 
    etc... 
}; 

define(function() { 
    var exports = {}; 

    exports.initialize = function(baseUrl, overridePaths, callback) { 
     if(!overridePaths) { 
     overridePaths = {}; 
     } 
     if(baseUrl && baseUrl[baseUrl.length - 1] != '/') { 
      baseUrl = baseUrl + '/'; 
     } 

     var fullpaths = {}; 
     for(var path in paths) { 
      // Don't add baseUrl to anything that looks like a full URL like 'http://...' or anything that begins with a forward slash 
      if(paths[path].match(/^(?:.*:\/\/|\/)/)) { 
       fullpaths[path] = paths[path]; 
      } 
      else { 
       fullpaths[path] = baseUrl + paths[path]; 
      } 
     } 

     var config = {paths: fullpaths}; 
     for(var pathName in overridePaths) { 
      config.paths[pathName] = overridePaths[pathName]; 
     } 
     require.config(config); 

     // Do anything else you need to do such as defining more functions for exports 

     if(callback) { 
      callback(); 
     } 
    } 

    return exports; 
}); 

Và sau đó trong main.js của dự án của tôi tập Tôi chỉ làm điều này:

require(['framework/main'], function(framework) { 
    // NOTE: This setTimeout() call is used because, for whatever reason, if you make 
    //  a 'require' call in here or in the framework without it, it will just hang 
    //  and never actually go fetch the files in the browser. There's probably a 
    //  better way to handle this, but I don't know what it is. 
    setTimeout(function() { 
     framework.initialize('framework', null, function() { 
      // Do stuff here 
     } 
    }, 0); 
}); 

Điều này nhận bất cứ điều gì được truyền vào phương thức initialize() của khung công tác cho 'baseURL' và thêm vào bất kỳ đường dẫn nào mà khung công tác định nghĩa không bắt đầu bằng dấu gạch chéo hoặc 'bất cứ điều gì: //', trừ khi chúng ghi đè đường dẫn. Điều này cho phép các gói bằng cách sử dụng khuôn khổ để ghi đè lên những thứ như 'jQuery'.

1

Một quá trình mà làm việc tốt cho tôi vì đã cho phép một gói với các môđun con sẽ được sử dụng trực tiếp từ dữ liệu chính hoặc từ một khung bên ngoài, giả định rằng một main.js (hoặc gói khác chính) được gọi bằng một tên cụ thể, đã sử dụng var baseUrl = require.toUrl('packageName') + '/../' làm tiền tố cho tệp cấu hình require.config({ paths: { ... } }). Ví dụ:

var music21Base = require.toUrl('music21') + '/../'; 

require.config({ paths: { 
          'jquery': music21Base + 'ext/jquery/jquery.2.1.10.min'; 
          'subModuleLoader': music21Base + 'src/subModuleLoader'; 
         } }); 

Việc ấn định context: "xxx" làm việc tốt cho gọi module bình thường với ./modName nhưng không làm việc cho các paths tranh cãi đối với tôi.

+1

Điều này không phải là rất gọn gàng nhưng nó giải quyết vấn đề tải applet địa phương của tôi. Cảm ơn! – Madwyn

Các vấn đề liên quan