【问题标题】:How to load a JS lib that defines a global and depends on another 3rd party lib using RquireJS?如何使用 RequireJS 加载定义全局并依赖于另一个 3rd 方库的 JS 库?
【发布时间】:2013-04-20 01:54:38
【问题描述】:

我正在尝试加载 KnockoutFire,这是一个使用 RequireJS 的 KnockoutJS 插件。只有1个文件:https://github.com/hiroshi/knockoutFire/blob/master/knockoutFire.js

插件做了​​两件事:

  1. 定义全局变量“KnockoutFire”
  2. 扩展核心 KnockoutJS ("ko") 库

因此,要正确加载此库,它需要能够通过全局变量“ko”访问 KnockoutJS。问题是我正在使用适当的 AMD 加载 KnockoutJS,并且没有可供 KnockoutFire 参考的全局“ko”。我曾尝试同时填充库和其他各种技巧以使其正常工作,但我很难过。一切都会产生错误:

ReferenceError: ko is not defined

这是我正在使用的:

require.config({
    enforceDefine: false,
    baseUrl: 'assets/js/',
    paths: {
        'knockout': '//ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1'
    },
    shim: {
        'knockout': { exports: 'ko' },
        'knockoutfire': { exports: 'KnockoutFire', deps: ['knockout'] }
    },
    waitSeconds : 15
});


require(['knockoutfire'], function() {
    log(KnockoutFire);
});

我也尝试过做一些奇怪的事情,比如:

require(['knockout'], function(ko) {
    require(['knockoutfire'], function(kofire, ko) {
        log(KnockoutFire);
    });
});

或者:

define(['knockout'], function(ko) {
    require(['knockoutfire'], function(ko) {
        log(KnockoutFire);
    });
});

如果我下载第三方库并将其添加到其中:

define(['knockout'], function(ko) {
    <!--- third party lib --->
});

一切正常。

有没有办法在不修改第三方库的情况下达到同样的效果?

【问题讨论】:

    标签: javascript knockout.js requirejs


    【解决方案1】:

    当您需要这些脚本时,请使用命令!插件http://requirejs.org/docs/1.0/docs/api.html#order 以确保您在淘汰赛之前加载淘汰赛。即在你的文件中:

    define('require','exports','order!knockout','order!knockoutfire',
             function(req,exp,knockout,knockoutfire){
                //trimmed 
    

    【讨论】:

    • 我只是尝试过,但无济于事。我认为问题在于“ko”永远不会成为全球性的,无论顺序如何。我更新了我的问题,看到最后。基本上,如果我只是在 lib 周围包装这个:“define(['knockout'], function(ko) {”,一切都会正常工作。有没有办法在 RequireJS 中伪造它而不修改 lib?
    • @Baz 您需要使用 shims 使一个不知道 requirejs 的文件神奇地知道 requirejs 而无需修改文件。看我的视频教程:youtu.be/4AGQpv0MKsA?t=4m25s
    【解决方案2】:

    我认为仔细查看http://knockoutjs.com/downloads/knockout-2.2.1.debug.js 可能会找到答案。有特殊的 AMD 处理,我不确定它是否与我尝试过的东西(使用 shim 和导出)配合得很好。

    这个技巧虽然有效。我们基本上使用bootstrap 模块控制全局分配。

    require.config({
        enforceDefine: false,
        baseUrl: 'assets/js/',
        paths: {
            'jquery': 'http://code.jquery.com/jquery-1.9.1',
            'knockout': 'http://knockoutjs.com/downloads/knockout-2.2.1.debug',
            'knockoutfire': 'https://raw.github.com/hiroshi/knockoutFire/master/knockoutFire'
        },
        waitSeconds: 15
    });
    
    define("bootstrap", ['jquery', 'knockout'], function ($, ko) {
        console.log("bootstrap", "jQuery " + $.fn.jquery, ko);
        window.ko = ko;
        var dfd = $.Deferred();
        require(['knockoutfire'], function (kof) {
            dfd.resolve(KnockoutFire);
        });
        return dfd.promise();
    });
    
    require(['bootstrap'], function (bootstrap) {
        bootstrap.then(function () {
            console.log("ko", ko, "KnockoutFire", KnockoutFire);
        });
    });
    

    输出:

    bootstrap jQuery 1.9.1  Object {exportSymbol: function, exportProperty: function, version: "2.2.1", utils: Object, cleanNode: function…}
    ko  Object {exportSymbol: function, exportProperty: function, version: "2.2.1", utils: Object, cleanNode: function…}
    KnockoutFire  Object {version: "0.0.3", utils: Object, observable: function, mapObservable: function}
    

    Example here.

    【讨论】:

    • 哇,太棒了!看到你的回答让果汁流淌,我认为它可以在没有承诺的情况下完成。这似乎有效:define("globalko", ['knockout'], function (ko) { window.ko = ko; }); require(['knockoutfire', 'globalko'], function (kofire) { console.log(kofire); });
    • 代码被吃掉了,所以我创建了一个专门的答案。 KOFire 的家伙愿意做一些小的改变来更好地支持 AMD,而不是完全致力于它——他们可以/应该做什么?
    【解决方案3】:

    这个答案的灵感来自@Paul 的回答:

    define("globalko", ['knockout'], function (ko) {
        window.ko = ko;
    });
    
    require(['knockoutfire', 'globalko'], function (kofire) {
        console.log(kofire);
    });
    

    这会加载两个库而不会出错。

    有人对 KO 或 KOFire 有什么建议可以让他们的库更容易与 AMD 一起使用吗?

    【讨论】:

    • 嗨。我不确定它是如何工作的。如果knockoutfireglobalko 之前加载,则会出现错误。这可能只是机会(或者它是内联定义而不是远程 JS 请求的事实 - 因此几乎可以肯定在淘汰赛之前执行)这意味着解决方案有效。我使用 Deferred 保证它。
    • 我认为最基本的问题是,knockout 的加载方式很聪明,而 knockoutfire 则不然。如果您将淘汰赛作为&lt;script&gt; 导入,而不是通过 AMD 导入,则 knockoutfire 将起作用,因为已设置全局 ko
    • 认为 knockoutfire 可以通过在其内容周围放置相同的神奇 AMD 加载程序并添加 knout 作为依赖项来修复。
    【解决方案4】:

    假设您在 knockoufire 中有类似以下的内容

    define('require','exports','ko',function(req,exp,ko){
    //trimmed 
    

    在knockoutfire之上尝试以下行:

    var ko = ko.ko
    

    【讨论】:

    • 我试图不必修改第 3 方库。
    猜你喜欢
    • 1970-01-01
    • 2011-02-27
    • 1970-01-01
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-27
    • 2015-04-18
    相关资源
    最近更新 更多