Using javascript code in MVC5 - where to put it

后端 未结 3 674
闹比i
闹比i 2020-12-09 18:21

Im having MVC5 application and in the view index.cshtml I need to use some java script code ,currently I put the script code inside the view and its working fine. My questi

相关标签:
3条回答
  • 2020-12-09 18:48

    The approach I've written down below is my way of extracting JavaScript completely from your views.

    • better to maintain (js issues -> look in js files and not in views)
    • modular approach
    • clear separation
    • better to understand by design

    In HTML5, use the data attribute to pass along variables from the Model. This helps tremendously in porting variables from MVC (your viewmodel) to javascript. This also allows you to keep javaScript stored in separate files as you probably would like in an MVC environment.

    1.1 Binding c# to HTML

    <div class="news" data-js-params="websiteName=@LocationWebsiteHelper.CurrentLocationWebsiteName()&amp;languageName=@languageName&amp;page=0&amp;itemsPerPage=@Model.MaxNumberOfItems">
    

    1.2 JS Helper functions to convert data into object literals

    Although built on jQuery, I've written 2 small functions which can help porting querystring variables into object literals and back. I use these throughout my js files:

    // @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 Convert HTML data into js object literals

    With these functions in mind you can pass any query string like variables into an object literal.

    var dataParams = convertQsToLiteral($('.news').data('js-params')); // get data attr
    var urlParams = convertQsToLiteral(window.location.search.substr(1)); // get url query string
    

    1.4 Example: JS modular setup to extend and override object literals

    Combined with jQuery's $.extend() function you can now override javascript objects in a modular approach (considering all closures a js file/module looks like this):

    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 Initializing a js module

    var module = new ProjectName.Module({ idea: 'even better' });
    

    2.1 Adding scripts/css to your views

    You have a couple options for attaching scripts to your views/pages/blocks:

    • section defined in the baselayout (only for partial views, directly included into the baselayout)
    • c# ClientResources (not the best approach in MVC but still doable, allows you to include external files into a partial view -> view in view)
    • bundles (good or minification and modular approach)

    2.2.1 baselayout setup for sections

    @RenderSection("AdditionalJS", false)
    

    2.2.2 usage partial view

    @section AdditionalJS
    {
        <script>
            var module = new ProjectName.Module({ idea: @Model.idea });
        </script>
    }
    

    2.3.1 baselayout setup for view in view

    @Html.Raw(Html.RequiredClientResources(RenderingTags.Header))
    

    2.3.2 usage view in view

    ClientResources.RequireScript("/Design/js/projectname.module.js").AtHeader();
    

    2.4.1 BundleConfig setup for scripts

    /// <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 baselayout setup

    ...
    <head>
        ...
        @BundleConfig.RenderConditionalScripts("lte IE 9", "~/bundles/polyfillJs")
        @Scripts.Render("~/bundles/libJs")
    <head>
    <body>
        ...
        @Scripts.Render("~/bundles/projectJs")        
    </body>
    
    0 讨论(0)
  • 2020-12-09 18:58

    You better use Razor @section for this.

    In your Layout:

    <html>
         <head>
              <title>My Title</title>
              .....
              @RenderSection("Scripts", false)
         </head>
    
         <body>
              @RenderBody
         </body>
    </html>
    

    In your View:

    <div id="container">
          <h3>Welcome!</h3>
          ...
    </div>
    
    @section Scripts
    {
        <script type="text/javascript">
            // your script goes here
        </script>
    }
    

    Some would prefer to place @RenderSection("Scripts") just before the </body> tag instead.

    0 讨论(0)
  • 2020-12-09 19:10

    If you have and HTML 5 template it really doesn't matter where you place the JavaScript code, If you haver a XHTML template you should put your code inside the <head></head> tags.

    Now with the best practices, right now the best practice is to put all your JS code just before your </body> closing tag. This way you make sure that your html elements tags have been parse by the browser.

    When going to a production environment the best is to concatenate all your JS into a single .js file and then have it minify, that way you would have an only small js file that the client browser needs to fetch.

    Minify your code

    The term minify in frontend code (css/js) stands for a process where you trim all your spaces and line breaks, and also the function scope variables get replace with a shorter name, usually just a vowel.

    function foo(someVar){
       return someVar;
    }
    

    when minified gets replaced to:

    function foo(e){return e}
    

    In MVC4 there was the Bundling and Minification feature that could help you with this. In MVC5 I'm not that sure.

    Further Reading: http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

    0 讨论(0)
提交回复
热议问题