【发布时间】:2014-04-06 11:14:48
【问题描述】:
我有 MVC5 应用程序,并且在视图 index.cshtml 中我需要使用 一些java脚本代码,目前我将脚本代码放在视图中并且工作正常。 我的问题是我应该把这段代码放在哪里(来自最佳实践)以及应该如何 我从视图中引用它?请举个例子。
【问题讨论】:
标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 razor
我有 MVC5 应用程序,并且在视图 index.cshtml 中我需要使用 一些java脚本代码,目前我将脚本代码放在视图中并且工作正常。 我的问题是我应该把这段代码放在哪里(来自最佳实践)以及应该如何 我从视图中引用它?请举个例子。
【问题讨论】:
标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 razor
我在下面写下的方法是我从您的视图中完全提取 JavaScript 的方法。
在 HTML5 中,使用 data 属性传递来自 Model 的变量。
这极大地有助于将变量从 MVC(您的视图模型)移植到 javascript。
这也允许您将 javaScript 存储在单独的文件中,就像您可能希望在 MVC 环境中一样。
1.1 将 c# 绑定到 HTML
<div class="news" data-js-params="websiteName=@LocationWebsiteHelper.CurrentLocationWebsiteName()&languageName=@languageName&page=0&itemsPerPage=@Model.MaxNumberOfItems">
1.2 将数据转换为对象字面量的 JS Helper 函数
虽然基于 jQuery,但我编写了 2 个小函数,可以帮助将查询字符串变量移植到对象文字中并返回。我在整个 js 文件中都使用这些:
// @param (qs): a query string of key value pairs (without ?)
// @param (keyDelimiter): string : character between values and keys
// @param (valDelimiter): string : character between keys and values
// @return (obj): an object literal
// @example: key1=val1&key2=val2&key3=val3
convertQsToLiteral: function (qs, keyDelimiter, valDelimiter) {
var arrParams, obj = {};
if (qs && qs.length) {
keyDelimiter = keyDelimiter || '&';
valDelimiter = valDelimiter || '=';
arrParams = qs.split(keyDelimiter);
$.each(arrParams, function (i, pair) {
var arrPair = pair.split(valDelimiter),
key = arrPair[0],
val = arrPair[1];
obj[key] = val;
});
}
return obj;
},
// @param (literal): an object literal key value paired of one level deep
// @param (keyDelimiter): string character between values and keys
// @param (valDelimiter): string : character between keys and values
// @return (string): array string representation
// @example: { key1: val1, key2: val2, key3: val3 }
convertLiteralToQs: function (literal, keyDelimiter, valDelimiter) {
var arrQs = [],
arrPairs, key;
keyDelimiter = keyDelimiter || '&';
valDelimiter = valDelimiter || '=';
for (key in literal) {
if (literal.hasOwnProperty(key)) {
arrPairs = [];
arrPairs.push(key, literal[key]);
arrQs.push(arrPairs.join(valDelimiter));
}
}
return arrQs.join(keyDelimiter);
},
1.3 将HTML数据转化为js对象字面量
考虑到这些函数,您可以将任何查询字符串(如变量)传递给对象字面量。
var dataParams = convertQsToLiteral($('.news').data('js-params')); // get data attr
var urlParams = convertQsToLiteral(window.location.search.substr(1)); // get url query string
1.4 示例:扩展和覆盖对象字面量的 JS 模块化设置
结合 jQuery 的 $.extend() 函数,您现在可以以模块化的方式覆盖 javascript 对象(考虑到 js 文件/模块的所有闭包看起来像这样):
window.ProjectName = (function($, projectname){
// default object literal
var cfg = {
// your default options
idea: 'great'
};
// @param (options): something like the cfg object
projectname.Module = function (options) {
this.settings = $.extend(true, {}, cfg, options); // deep copy
this.init();
};
projectname.Module.prototype = {
init: function(){
this.idea = this.settings.idea;
console.log(this.idea);
}
};
return projectname;
}(window.jQuery, window.ProjectName));
1.5 初始化一个js模块
var module = new ProjectName.Module({ idea: 'even better' });
2.1 向视图中添加脚本/css
您有几个选项可以将脚本附加到您的视图/页面/块:
ClientResources(不是 MVC 中的最佳方法,但仍然可行,允许您将外部文件包含到部分视图中 -> 视图中)2.2.1 部分的基本布局设置
@RenderSection("AdditionalJS", false)
2.2.2 使用局部视图
@section AdditionalJS
{
<script>
var module = new ProjectName.Module({ idea: @Model.idea });
</script>
}
2.3.1 视图中视图的基本布局设置
@Html.Raw(Html.RequiredClientResources(RenderingTags.Header))
2.3.2 使用视图中的视图
ClientResources.RequireScript("/Design/js/projectname.module.js").AtHeader();
2.4.1 脚本的 BundleConfig 设置
/// <summary>
/// Register the Javascript bundles
/// Separated in libJs, projectJs and polyfillJs
/// </summary>
/// <param name="bundles"></param>
private static void RegisterScripts(BundleCollection bundles)
{
// usage for libraries
bundles.Add(new ScriptBundle(
"~/bundles/libJs").Include(
"~/Design/js/lib/*.js"
));
// project object
bundles.Add(new ScriptBundle(
"~/bundles/projectJs").Include(
"~/Design/js/project.dev.js",
"~/Design/js/classes/*.js",
"~/Design/js/components/*.js"
));
// usage for browser support
bundles.Add(new ScriptBundle(
"~/bundles/polyfillJs").Include(
"~/Design/js/polyfills/*.js"
));
}
/// <summary>
/// Render scripts inside conditional comments
/// http://stackoverflow.com/questions/12865939/mvc4-bundling-minification-with-ie-conditional-comments
/// </summary>
/// <param name="ie"></param>
/// <param name="paths"></param>
/// <returns></returns>
public static IHtmlString RenderConditionalScripts(string ie, params string[] paths)
{
var tag = string.Format("<!--[if {0}]>{1}<![endif]-->", ie, Scripts.Render(paths));
return new MvcHtmlString(tag);
}
2.4.2 基本布局设置
...
<head>
...
@BundleConfig.RenderConditionalScripts("lte IE 9", "~/bundles/polyfillJs")
@Scripts.Render("~/bundles/libJs")
<head>
<body>
...
@Scripts.Render("~/bundles/projectJs")
</body>
【讨论】:
section。 “hack”,如果你可以这么称呼的话,就是使用ClientResource。
为此,您最好使用 Razor @section。
在您的布局中:
<html>
<head>
<title>My Title</title>
.....
@RenderSection("Scripts", false)
</head>
<body>
@RenderBody
</body>
</html>
在你看来:
<div id="container">
<h3>Welcome!</h3>
...
</div>
@section Scripts
{
<script type="text/javascript">
// your script goes here
</script>
}
有些人更愿意将@RenderSection("Scripts") 放在</body> 标记之前。
【讨论】:
如果您有 HTML 5 模板,那么将 JavaScript 代码放在哪里并不重要,如果您有 XHTML 模板,您应该将代码放在 <head></head> 标记内。
现在有了最佳实践,现在最佳实践是将所有 JS 代码放在 </body> 结束标记之前。这样你就可以确保你的 html 元素标签已经被浏览器解析了。
进入生产环境时,最好将所有 JS 连接到一个 .js 文件中,然后将其缩小,这样您就只有一个小的 js 文件,客户端浏览器需要获取该文件。
前端代码 (css/js) 中的术语 minify 表示您修剪所有空格和换行符的过程,并且函数范围变量被替换为更短的名称,通常只是一个元音。
function foo(someVar){
return someVar;
}
当缩小被替换为:
function foo(e){return e}
MVC4 中的捆绑和缩小功能可以帮助您解决此问题。 MVC5 我不太确定。
延伸阅读:http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
【讨论】: