twitter-bootstrap RequireJS 的 Shim Twitter Bootstrap

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13377373/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 15:42:37  来源:igfitidea点击:

Shim Twitter Bootstrap for RequireJS

twitter-bootstraprequirejs

提问by Johan Alkst?l

The RequireJS docssay that to support older versions of IE, you need to configure enforceDefine: true.

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

So if you want to support Internet Explorer, catch load errors, and have modular code either through direct define() calls or shim config, always set enforceDefine to be true. See the next section for an example.

NOTE: If you do set enforceDefine: true, and you use data-main="" to load your main JS module, then that main JS module must call define() instead of require() to load the code it needs. The main JS module can still call require/requirejs to set config values, but for loading modules it should use define().

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

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

Since Twitter Bootstrap isn't an AMD module, I need to shim it for it to work. This is how I configure it;

由于 Twitter Bootstrap 不是 AMD 模块,我需要对它进行填充才能使其工作。这就是我配置它的方式;

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

Later when my module wants bootstrap as a dependency, I still end up with an error message;

稍后当我的模块想要引导程序作为依赖项时,我仍然以错误消息告终;

Error: No define call for bootstrap

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

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

If I've understood the docs correctly, enforceDefineshould ignore shims but it's not.

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

What am I doing wrong here?

我在这里做错了什么?

采纳答案by Karolis

According to the docs that error is thrown if "Script was part of a shim config that specified a global string property that can be checked for loading, and that check failed."

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

To fix this you need to add exports value in the shim config so that RequireJS can check whether the script was succesfully loaded. In case of Bootstrap that's slightly tricky as Bootstrap doesn't 'export' a propert global variable only a bunch of jquery plugins, but you can use any of those plugins as an export value e.g. $.fn.popover:

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

{
    paths: {
        "bootstrap": "../bootstrap",
        "jquery": "../jquery-1.8.2"
    },
    shim: {
        "bootstrap": {
          deps: ["jquery"],
          exports: "$.fn.popover"
        }
    },
    enforceDefine: true
}

回答by Patrick Hammer

Instead of doing the magic with shim, I converted the bootstrap JS into a module:

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

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

Everything else I found in the forums and on stackoverflow did not work for me because I get jQuery from the CDN. I assume because I hit the issue as described in the requireJS doc on http://requirejs.org/docs/api.html

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

Do not mix CDN loading with shim config in a build. Example scenario: you load jQuery from the CDN but use the shim config to load something like the stock version of Backbone that depends on jQuery. When you do the build, be sure to inline jQuery in the built file and do not load it from the CDN. Otherwise, Backbone will be inlined in the built file and it will execute before the CDN-loaded jQuery will load. This is because the shim config just delays loading of the files until dependencies are loaded, but does not do any auto-wrapping of define. After a build, the dependencies are already inlined, the shim config cannot delay execution of the non-define()'d code until later. define()'d modules do work with CDN loaded code after a build because they properly wrap their source in define factory function that will not execute until dependencies are loaded. So the lesson: shim config is a stop-gap measure for for non-modular code, legacy code. define()'d modules are better.

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

Converting the bootstrap into a ordinary AMD module and removing the shim config solved it for me. Only drawback: you cannot retrieve bootstrap from the bootstrap CDN.

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

回答by lexeme

I use this configuration inside my project:

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

startup.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();
    });
});

then in my code I use this:

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

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
         // ...

回答by Jasper Moelker

@lexeme & @benjaminbenben how about wrapping this concept in a RequireJS plugin which creates the shim, requires jQuery and also returns jQuery so you wouldn't need to include this manually?

@lexeme & @benjaminbenben 如何将这个概念包装在 RequireJS 插件中,该插件创建 shim,需要 jQuery 并返回 jQuery,这样您就不需要手动包含它了?

To use a bootstrap component you would simply use:

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

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

And you would use this require-bootstrap-pluginto make it work.

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