我是否正确构建我的JavaScript以遵守AMD规范?

时间:2014-01-24 00:02:07

标签: jquery requirejs amd js-amd

我已按照this question开始使用RequireJS以及RequireJS jQuery Docs。我无法找到如何在单个文件中重用包或如何构建文件本身。以下代码按预期工作,并在页面上显示文本。 javascript的第一部分会自动创建see this question for more details

我关注的部分是AMDSpecs.js init方法。这似乎适合AMD的规格。如果是这种情况,每次需要jQuery时是否需要调用require?我希望我在解释我的意思,请询问您是否需要更多信息。

HTML

<div id="output"></div>

的Javascript

<script src="/MVCTesting/Scripts/ThirdParty/RequireJS/require.js"></script>
<script type="text/javascript">
     require( [ "/MVCTesting/Scripts/AMD/core.js" ], function() {
     require( ["jquery", "/MVCTesting/Scripts/AMD/views/jquery/AMDSpecs.js"],                 
        function($, pm) {
           if (pm != undefined && pm.init) {
              pm.init($);
           }
        });
     });
</script>

/*AMDSpecs.js*/
define(function () {
    //Do setup work here

    return {
        $: undefined,
        setupEvents: function () {
            $("#output").text("jQuery is working!");
        },
        init: function ($) {
            this.$ = $;

            require(["Views/JQuery/AMDSpecs"], function (specs) {
                specs.setupEvents();
            });
        }
    };
});

更新

在唐纳德回答所有代码之后,这是我的工作解决方案。注意,我仍然需要在模块名称中包含.js,但这会简化过程。

HtmlExtension.cs

    /// <summary>
    /// An Html helper for Require.js
    /// </summary>
    /// <param name="helper"></param>
    /// <param name="module">Location of the main.js file.</param>
    /// <returns></returns>
    public static MvcHtmlString RequireJS(this HtmlHelper helper, string module)
    {
        const string jsLocation = "Scripts/AMD/";

        //Don't build require string if there is not an amd script
        if (!File.Exists(helper.ViewContext.HttpContext.Server.MapPath(
                    GetAbsolutePath(Path.Combine(jsLocation, module + ".js")))))
        {
            return null;
        }

        var require = new StringBuilder();

        require.AppendLine("    require( [\"" + GetAbsolutePath(jsLocation + module + ".js") + "\"], function(pm) {");
        require.AppendLine("        if (pm != undefined && pm.init) {");
        require.AppendLine("            pm.init();");
        require.AppendLine("        }");
        require.AppendLine("    });");

        return new MvcHtmlString(require.ToString());
    }

    /// <summary>
    /// Convert the path to work in IIS for MVC
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    private static string GetAbsolutePath(string path)
    {
        return VirtualPathUtility.ToAbsolute("~/" + path);
    }

    /// <summary>
    /// Create the include for RequireJS based on the current page
    /// </summary>
    /// <param name="helper"></param>
    /// <returns></returns>
    public static MvcHtmlString ViewSpecificRequireJS(this HtmlHelper helper)
    {
        var action = helper.ViewContext.RouteData.Values["action"];
        var controller = helper.ViewContext.RouteData.Values["controller"];

        return helper.RequireJS(string.Format("views/{0}/{1}", controller, action));
    }

_Layout.cshtml (MVCTesting是我的项目名称)

<script data-main="/MVCTesting/Scripts/AMD/core.js" src="~/Scripts/ThirdParty/RequireJS/require.js"></script>

AMDSpecs.js

define(["jquery"], function ($) {
    //Do setup work here

    return {
        setupEvents: function () {
            $("#output").text("jQuery is working!");
        },
        init: function () {
            this.setupEvents();
        }
    };
});

1 个答案:

答案 0 :(得分:2)

不,你没有做得很好。您是“主要”JavaScript文件,由(唯一的)data-main标记的<script>属性定义,应该启动应用。所有其他JavaScript文件应代表“模块”,即与特定目的相关的功能集合。

请注意,我不明白您的应用正在做什么,所以希望以下示例至少可以帮助您入门。

<强> 1。加载主脚本:

<script data-main="main" src="/MVCTesting/Scripts/ThirdParty/RequireJS/require.js"></script>

<强> 2。 “main.js”开启应用程序:

require(["AMDSpecs"], function(specs) {
  specs.init();
});

第3。将脚本分解为代表“模块”的单个文件。在这种情况下,您的“AMDSpecs”是一个模块:

/* AMDSpecs.js */

define(["jquery"], function($) {
  // do setup work here

  return {
    setupEvents: function() {
      $("#output").text("jQuery is working!");
    },
    init: function() {
      this.setupEvents();
    }
  };

});

请注意,在require次调用中嵌入require次调用没有帮助,除非有理由有条件或懒惰地加载脚本。

P.S。在需要脚本时不要使用“.js”扩展名 - 这是由RequireJS自动完成的。