Javascript - 为 requireJS 构建插件

Javascript - build plugin for requireJS

我写了一个 Javascript 插件,我想让它与 requireJS 兼容。但是,我很难让它正常工作。我认为我的 AMD 写得不正确或类似这样的东西。

当我尝试执行插件构造函数时,它在 requireJS 加载脚本后未定义(来自 requirejs 的回调变量也未定义)。

例如我这样使用 requirejs:

requirejs([
'./assets/js/myplugin.js'
], function( myplugin) {

    console.log(myplugin); // undefined
    new MyPlugin(); // undefined

});

在 myplugin.js 我有这个脚本:

(function (root, factory) { 

if (typeof define === 'function' && define.amd) {

    define(
        'myplugin',
        ['brandname-util1/util1',
        'brandname-util2/util2',
        'brandname-util3/util3'],
        factory
    );

} else if (typeof exports === 'object' && module.exports) {

    module.exports = factory(
        root,
        require('brandname-util1'),
        require('brandname-util2'),
        require('brandname-util3')
    );

} else {

    root.MyPlugin = factory(
        root,
        root.BrandNameUtil1,
        root.BrandNameUtil2,
        root.BrandNameUtil3
    );

}

}(this, function factory(root, util1, util2, util3) {

    'use strict';

    var MyPlugin = function() {
    }

    return MyPlugin;

}));

脚本已正确加载(异步),但未定义任何内容。我不确定是否完全理解它是如何工作的。

编辑:这里是 utils 脚本示例:

// util1
(function(root, factory) {

    if (typeof define === 'function' && define.amd) {

        define(
            'brandname-util1/util1',
            ['jquery'],
            factory
        );

    } else if (typeof module === 'object' && module.exports) {

        module.exports = factory(require('jquery'));

    } else {

        root.BrandNameUtil1 = factory(root);

    }

}(this, function() {

    "use strict";

    var util1 = {};

    // declare some functions

    return util1;

}));

// util2
(function(root, factory) {

    if (typeof define === 'function' && define.amd) {

        define(
            'brandname-util2/util2',
            ['jquery'],
            factory
        );

    } else if (typeof module === 'object' && module.exports) {

        module.exports = factory(require('jquery'));

    } else {

        root.BrandNameUtil2 = factory(root);

    }

}(typeof window !== "undefined" ? window : this, function() {

    "use strict";

    var util2 = function() {},
        proto = util2.prototype;

    // declare some proto

    return util2;

}));

// util3
(function (root, factory) { 

    if (typeof define === 'function' && define.amd) {

        define(
            'brandname-util3/util3',
            ['brandname-util1/util1',
            'brandname-util2/util2'],
            factory
        );

    } else if (typeof module === 'object' && module.exports) {

        module.exports = factory(
            root,
            require('brandname-util1'),
            require('brandname-util2')
        );

    } else {

        root.BrandNameUtil3 = factory(
            root,
            root.BrandNameUtil1,
            root.BrandNameUtil2
        );

    }

}(this, function (root, util1, util2) {

    "use strict";

    var util3 = function() {},
        proto = util3.prototype;

    // declare some proto

    return util3;

}));

我看到的唯一问题是您的工厂将 root 作为第一个参数,然后是模块。它在 CommonJS(第二个分支)和没有模块系统(第三个分支)中运行良好,但在 AMD 情况下(第一个分支)失败,因为 define 将仅使用 3 个参数调用您的工厂:root将被设置为依赖列表的第一个模块,util3不会被设置,等等

如果你在你的工厂中实际上没有使用root,你可以将它从参数列表中删除并调整第二和第三分支中的调用不通过它,一切都应该有效。

否则,如果你的工厂确实需要它,你可以通过更改第一个分支来修复它:

define(['brandname-util1/util1',
    'brandname-util2/util2',
    'brandname-util3/util3'],
    factory.bind(undefined, root)
);

这会将工厂中 this 的值设置为 undefined(应该没问题)并强制将工厂中的第一个参数设置为值 root在您的 define 调用范围内。然后在其后附加模块。

有关 bind 的更多详细信息,请参阅此文档。

您也不应在 define 调用中设置模块名称。我在上面显示的调用删除了模块名称。该调用应该只有依赖列表和工厂。

而且你不应该把 .js 放在模块名称中。所以 requirejs(['./assets/js/myplugin'], 没有 .js.