AMD/Require JS - 如何仅按需加载文件

dar*_*ong 6 lazy-loading amd requirejs backbone.js js-amd

我有一些AMD/Require.js问题.我对模块化js和AMD都很陌生,所以如果有人能帮我解决这个问题会很棒.

假设我的系统上有2个不同的区域,定义为模块("define()"函数 - 我正在使用Backbone,顺便说一句)

  • 图书
    • BookItemView.js
    • BookModel.js
    • BookCollection.js
  • DVDS
    • DvdItemView.js
    • DvdModel.js
    • DvdCollection.js

我注意到,如果用户当前正在访问该站点的"Books"部分,则DVD部分中的文件也包含在Require.js中.我有以下问题:

  • 有没有办法只包含与活动网站部分相关的文件?在某些情况下,用户不想看DVD列表,甚至不允许这样做.我想让服务器不要发出不必要的HTTP请求.有没有机会使用Require.js这样做?

任何想法都会很好.

Jon*_*ues 3

这是可能的,但很大程度上取决于您构建 JS 应用程序的方式。另外,我假设您这里有一个 Backbone 应用程序。对于不同的框架有不同的方法。

例如,您可能有一个app.js看起来像这样的:

define([
    'DvdItemView', 'DvdModel', 'DvdCollection', 
    'BookItemView', 'BookModel', 'BookCollection'
], function(DvdView, DvdModel, DvdCol, BookView, BookModel, BookCol) {

   // router declarations go here

});
Run Code Online (Sandbox Code Playgroud)

因为您根据上述模块“定义”了该模块,所以它们始终会在运行路由器代码之前加载。正如 @alexndm 指出的,如果你在上面运行 r.js,你实际上可以将所有模块合并为一个。

然而,正如您所提到的,一旦应用程序达到一定大小,您想要的就是根据用户正在交互的内容来延迟加载不同的部分。这更多的是一个应用程序的问题,RequireJS 在这方面只能帮助你这么多。我相信最好的方法是在路由器中。

routes: {
    '/books': 'booksList',
    '/books/:id': 'booksDetail',
    '/dvds': 'dvdList',
    '/dvds/:id': 'dvdDetail'
},

booksList: function() {
    if (!booksDepsLoaded) {
        // Here we go and load the appropriate files
        require(['BooksArea'], function(BooksArea) {
            // BooksArea.Model, BooksArea.Collection, etc...
            // do stuff to render a book list..
        })
    }
},

...
Run Code Online (Sandbox Code Playgroud)

这是非常幼稚的伪代码。您可能需要编写一些通用代码来处理仍然需要加载依赖项的路由以及错误处理等。

不过,要掌握的重要概念是,您需要在应用程序/路由器启动之前定义路由 - 然后您需要异步代码来处理获取模块。

  • 如果您正在寻找一些有用的 RequireJS 模式,请查看 [Durandal.js](https://github.com/BlueSpire/Durandal)。他们使用基于 Sammy.JS 的路由器,但概念相似。 (2认同)