Правильно ли я собираю свой JavaScript для соответствия спецификациям AMD?
Я следовал за этим вопросом, чтобы начать использовать RequireJS, а также RequireJS jQuery Docs. Я не смог найти, как повторно использовать пакеты в одном файле или как структурировать сам файл. Следующий код работает должным образом и отображает текст на странице. Первая часть javascript создается автоматически, см. Этот вопрос для получения более подробной информации.
Часть, которая меня интересует, - это метод инициализации AMDSpecs.js. Это кажется контрпродуктивным для спецификаций AMD. Если это так, нужно ли мне вызывать require каждый раз, когда мне нужен jQuery? Я надеюсь, что объясню, что я имею в виду, пожалуйста, спросите, если вам нужна дополнительная информация.
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 ответ
Нет, вы делаете это не совсем правильно. Вы "основной" файл 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
вызовы, если нет причин для условной или ленивой загрузки скрипта.
PS Не используйте расширение ".js", когда требуются скрипты - это делается автоматически RequireJS.