【问题标题】:Using java script code in MVC5 - where to put it在 MVC 5 中使用 javascript 代码 - 放在哪里
【发布时间】:2014-04-06 11:14:48
【问题描述】:

我有 MVC5 应用程序,并且在视图 index.cshtml 中我需要使用 一些java脚本代码,目前我将脚本代码放在视图中并且工作正常。 我的问题是我应该把这段代码放在哪里(来自最佳实践)以及应该如何 我从视图中引用它?请举个例子。

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 razor


    【解决方案1】:

    我在下面写下的方法是我从您的视图中完全提取 JavaScript 的方法。

    • 更好地维护(js 问题 -> 查看 js 文件而不是视图)
    • 模块化方法
    • 清晰的分离
    • 通过设计更好地理解

    在 HTML5 中,使用 data 属性传递来自 Model 的变量。 这极大地有助于将变量从 MVC(您的视图模型)移植到 javascript。 这也允许您将 javaScript 存储在单独的文件中,就像您可能希望在 MVC 环境中一样。

    1.1 将 c# 绑定到 HTML

    <div class="news" data-js-params="websiteName=@LocationWebsiteHelper.CurrentLocationWebsiteName()&amp;languageName=@languageName&amp;page=0&amp;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

    您有几个选项可以将脚本附加到您的视图/页面/块:

    • 在 baselayout 中定义的部分(仅用于部分视图,直接包含在 baselayout 中)
    • c# 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>
    

    【讨论】:

    • 感谢蒂姆投了赞成票,你写了几种方法,我使用 2.2.1 和 2.2.2,知道为什么它不起作用,即脚本代码没有被调用...
    • 我假设您不在局部视图中,并且已经完成了将视图包含到另一个局部视图中的技巧。 MVC 不允许您为此使用section。 “hack”,如果你可以这么称呼的话,就是使用ClientResource
    • 为 bundlesetup 添加了第三个选项。一个答案中有很多东西/研究,所以我希望它可以帮助你和其他人^^
    【解决方案2】:

    为此,您最好使用 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") 放在&lt;/body&gt; 标记之前。

    【讨论】:

    • 按照我所说的,脚本保留在脚本部分的视图中,不是吗?另外我不确定我是否理解我应该在布局中做什么这是我应该修改的代码? @ViewBag .Title - 我的 ASP.NET 应用程序 @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr")
    【解决方案3】:

    如果您有 HTML 5 模板,那么将 JavaScript 代码放在哪里并不重要,如果您有 XHTML 模板,您应该将代码放在 &lt;head&gt;&lt;/head&gt; 标记内。

    现在有了最佳实践,现在最佳实践是将所有 JS 代码放在 &lt;/body&gt; 结束标记之前。这样你就可以确保你的 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

    【讨论】:

    • 谢谢,但你所说的缩小是什么意思,你能提供例子吗?
    • @shopiaT 我刚刚添加了一个 Minify 示例,并在底部添加了一个指向 asp.NET MVC 中的捆绑和缩小功能的链接。请查看该链接以了解 microsoft 推荐的最佳做法。
    猜你喜欢
    • 2012-08-20
    • 2015-09-23
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 2014-11-21
    • 2015-10-31
    相关资源
    最近更新 更多