37

RequireJS文档说要支持旧版本的 IE,您需要配置enforceDefine: true.

因此,如果您想支持 Internet Explorer、捕获加载错误并通过直接 define() 调用或 shim 配置来编写模块化代码,请始终将 enforceDefine 设置为 true。有关示例,请参见下一节。

注意:如果你确实设置了 enforceDefine: true,并且你使用 data-main="" 来加载你的主 JS 模块,那么那个主 JS 模块必须调用 define() 而不是 require() 来加载它需要的代码。主 JS 模块仍然可以调用 require/requirejs 来设置配置值,但是对于加载模块,它应该使用 define()。

由于 Twitter Bootstrap 不是 AMD 模块,因此我需要对其进行填充以使其正常工作。这就是我的配置方式;

<script type="text/javascript">
    var require = {
        paths: {
            "bootstrap": "../bootstrap",
            "jquery": "../jquery-1.8.2"
        },
        shim: {
            "bootstrap": ["jquery"]
        },
        enforceDefine: true
    };
</script>

后来,当我的模块想要将引导程序作为依赖项时,我仍然会收到一条错误消息;

Error: No define call for bootstrap

http://requirejs.org/docs/errors.html#nodefine

如果我正确理解了文档,enforceDefine应该忽略垫片,但事实并非如此。

我在这里做错了什么?

4

4 回答 4

37

根据文档,如果“脚本是 shim 配置的一部分,该配置指定了可以检查加载的全局字符串属性,并且该检查失败,则会引发错误。”

要解决此问题,您需要在 shim 配置中添加导出值,以便 RequireJS 可以检查脚本是否已成功加载。如果 Bootstrap 有点棘手,因为 Bootstrap 不会“导出”属性全局变量,只有一堆 jquery 插件,但您可以使用这些插件中的任何一个作为导出值,例如$.fn.popover

{
    paths: {
        "bootstrap": "../bootstrap",
        "jquery": "../jquery-1.8.2"
    },
    shim: {
        "bootstrap": {
          deps: ["jquery"],
          exports: "$.fn.popover"
        }
    },
    enforceDefine: true
}
于 2012-11-25T23:51:03.753 回答
14

我没有用 shim 施展魔法,而是将引导 JS 转换为一个模块:

define([ "jquery" ], function($) {
  // bootstrap JS code
});

我在论坛和 stackoverflow 上找到的所有其他内容都对我不起作用,因为我从 CDN 获得了 jQuery。我假设是因为我遇到了http://requirejs.org/docs/api.html上的 requireJS 文档中描述的问题

不要在构建中混合 CDN 加载和 shim 配置。示例场景:您从 CDN 加载 jQuery,但使用 shim 配置加载依赖于 jQuery 的 Backbone 的库存版本。进行构建时,请确保在构建文件中内联 jQuery,并且不要从 CDN 加载它。否则,Backbone 将内联在构建的文件中,并在加载 CDN 的 jQuery 加载之前执行。这是因为 shim 配置只是延迟加载文件,直到加载依赖项,但不执行任何自动包装定义。构建后,依赖项已经内联,shim 配置不能延迟执行未定义()的代码,直到以后。定义()' d 模块在构建后确实与 CDN 加载的代码一起工作,因为它们正确地将其源代码包装在定义工厂函数中,该函数在加载依赖项之前不会执行。所以教训:shim config 是非模块化代码、遗留代码的权宜之计。定义()的模块更好。

将引导程序转换为普通的 AMD 模块并删除 shim 配置为我解决了这个问题。唯一的缺点:您无法从引导 CDN 中检索引导。

于 2013-03-15T19:01:12.543 回答
11

我在我的项目中使用这个配置:

启动.js

require.config({
    paths: {
        /* other paths are omitted */
        'bootstrap': '../libs/bootstrap'
    },
    shim: {
        'bootstrap/bootstrap-slider': { deps: ['jquery'], exports: '$.fn.slider' }, 
        'bootstrap/bootstrap-affix': { deps: ['jquery'], exports: '$.fn.affix' },
        'bootstrap/bootstrap-alert': { deps: ['jquery'], exports: '$.fn.alert' },
        'bootstrap/bootstrap-button': { deps: ['jquery'], exports: '$.fn.button' },
        'bootstrap/bootstrap-carousel': { deps: ['jquery'], exports: '$.fn.carousel' },
        'bootstrap/bootstrap-collapse': { deps: ['jquery'], exports: '$.fn.collapse' },
        'bootstrap/bootstrap-dropdown': { deps: ['jquery'], exports: '$.fn.dropdown' },
        'bootstrap/bootstrap-modal': { deps: ['jquery'], exports: '$.fn.modal' },
        'bootstrap/bootstrap-popover': { deps: ['jquery'], exports: '$.fn.popover' },
        'bootstrap/bootstrap-scrollspy': { deps: ['jquery'], exports: '$.fn.scrollspy'        },
        'bootstrap/bootstrap-tab': { deps: ['jquery'], exports: '$.fn.tab' },
        'bootstrap/bootstrap-tooltip': { deps: ['jquery'], exports: '$.fn.tooltip' },
        'bootstrap/bootstrap-transition': { deps: ['jquery'], exports: '$.support.transition' },
        'bootstrap/bootstrap-typeahead': { deps: ['jquery'], exports: '$.fn.typeahead'  },
    }
});

require(['domReady', 'app'], function(domReady, app) {
    domReady(function() {
        app.init();
    });
});

然后在我的代码中我使用这个:

define(['jquery', 'underscore', 'backbone', 'text!templates/photos-list.html'], function($, _, Backbone, html) {
    var PhotosListView = Backbone.View.extend({
        viewImageFullscreen: function(e) {
            e.preventDefault();

            require(['bootstrap/bootstrap-modal', 'text!templates/photo-modal.html'], function(modal, htmlModal) {
                 var modalTemplate = _.template(htmlModal, options);
                 $('body').append(modalTemplate);

                 // setup
                 $(selector + '_modal').modal({
                     backdrop: true,
                     keyboard: true,
                     show: false
                 }).css({
                     'width': function() { return ($(document).width() * 0.55) + 'px'; },
                     'margin-left': function() { return -($(this).width() * 0.5); }
                 });

                 // trigger `modal` 
                 $(selector + '_modal').modal('show');
             }); // require() call
         // ...
于 2013-09-25T13:54:35.703 回答
4

@lexeme 和 @benjaminbenben 将这个概念包装在一个 RequireJS 插件中如何创建垫片,需要 jQuery 并且还返回 jQuery,所以你不需要手动包含它?

要使用引导组件,您只需使用:

define(['bootstrap!tooltip'], function($){
  $('[data-toggle="tooltip"]').tooltip();
});

你会使用这个require-bootstrap-plugin来使它工作。

于 2014-05-25T17:09:50.123 回答