【问题标题】:Access a Model property in a javascript file?访问 javascript 文件中的模型属性?
【发布时间】:2011-11-29 09:53:04
【问题描述】:

是否可以访问外部 Javascript 文件中的模型属性?

例如在“somescript.js”文件中

var currency = '@Model.Currency';
alert(currency);

在我看来

<script src="../../Scripts/somescript.js" type="text/javascript">

这似乎不起作用,但是如果我将 javascript 直接放入脚本标签内的视图中,那么它是否有效?这意味着必须始终将代码放在页面中,而不是像这样加载外部脚本文件:

@model MyModel;

<script lang=, type=>
var currency = '@Model.Currency';
alert(currency);
</script>

有没有办法解决这个问题?

【问题讨论】:

  • 如果您可以生成外部 js 文件,那么他们的浏览器会缓存您动态生成的视图模型数据。可能不是你想要的?
  • 我最近写了一篇关于如何[使用部分 Razor 视图生成外部 JavaScript 文件][博文]的博客。博客文章展示了如何使用自定义操作过滤器来解析外部 JavaScript 文件中的 Razor 代码。 tl;dr: 是的,可以使用一个简单但聪明的解决方法。 [博文]:blog.mariusschulz.com/…
  • stackoverflow.com/a/41312348/2592042这里已经详细解释过了。
  • @Rajshekar Reddy - 您的所有实现都不能在视图页面之外工作 - 即在外部 js 文件中。

标签: c# javascript asp.net-mvc-3 model razor


【解决方案1】:

我使用数据属性和 jQuery 解决了这个问题。它使代码非常易读,并且不需要部分视图或通过 ViewEngine 运行静态 javascript。 JavaScript 文件是完全静态的,会正常缓存。

Index.cshtml:

@model Namespace.ViewModels.HomeIndexViewModel
<h2>
    Index
</h2>

@section scripts
{
    <script id="Index.js" src="~/Path/To/Index.js"
        data-action-url="@Url.Action("GridData")"
        data-relative-url="@Url.Content("~/Content/Images/background.png")"
        data-sort-by="@Model.SortBy
        data-sort-order="@Model.SortOrder
        data-page="@ViewData["Page"]"
        data-rows="@ViewData["Rows"]"></script>
}

Index.js:

jQuery(document).ready(function ($) {
    // import all the variables from the model
    var $vars = $('#Index\\.js').data();

    alert($vars.page);
    alert($vars.actionUrl); // Note: hyphenated names become camelCased
});

_Layout.cshtml(可选,但好习惯):

<body>
    <!-- html content here. scripts go to bottom of body -->

    @Scripts.Render("~/bundles/js")
    @RenderSection("scripts", required: false)
</body>

【讨论】:

    【解决方案2】:

    没有办法在JS文件中实现MVC/Razor代码。

    您应该在 HTML 中设置变量数据(在 .cshtml 文件中),这在概念上是可以的,并且不会违反关注点分离(服务器生成的 HTML 与客户端脚本代码),因为如果您考虑一下,这些变量值是服务器关注的问题。

    看看这个(部分但很好的)解决方法:Using Inline C# inside Javascript File in MVC Framework

    【讨论】:

    • 这是一个很好的解决方案。我可以将所有“静态”javascript 保存在一个文件中,然后将“vars”部分放入部分视图中并加载它。不错:)
    【解决方案3】:

    您可以做的是将剃刀标签作为变量传递。

    在剃刀文件中>

    var currency = '@Model.Currency';
    doAlert(currency);
    

    在JS文件中>

    function doAlert(curr){
       alert(curr);
    }
    

    【讨论】:

      【解决方案4】:

      试试 JavaScriptModel (http://jsm.codeplex.com):

      只需将以下代码添加到您的控制器操作中:

      this.AddJavaScriptVariable("Currency", Currency);
      

      现在您可以在 JavaScript 中访问变量“货币”。

      如果该变量应该在孔位上可用,请将其放入过滤器中。可以在文档中找到如何使用过滤器中的 JavaScriptModel 的示例。

      【讨论】:

        【解决方案5】:

        我所做的是使用方法调用模式创建一个 js 对象,然后您可以从外部 js 文件中调用它。由于 js 使用全局变量,因此我将其封装以确保不会与其他 js 库发生冲突。 例子: 在视图中

         @section scripts{
                <script>
                    var thisPage = {
                        variableOne: '@Model.One',
                        someAjaxUrl: function () { return '@Url.Action("ActionName", "ControllerName")'; }            
                    };
                </script>
                @Scripts.Render("~/Scripts/PathToExternalScriptFile.js")   
            }
        

        现在在外部页面内部,您可以获取具有受保护范围的数据,以确保它不会与 js 中的其他全局变量冲突。

          console.log('VariableOne = ' + thisPage.variableOne);
          console.log('Some URL = ' + thisPage.someAjaxUrl());
        

        您还可以将其包装在外部文件中的模块内,以使其更加防冲突。 示例:

        $(function () {
            MyHelperModule.init(thisPage || {});
        });
        
        var MyHelperModule = (function () {
            var _helperName = 'MyHelperModule';
        
            // default values
            var _settings = { debug: false, timeout:10000, intervalRate:60000};    
        
            //initialize the module
            var _init = function (settings) {
        
                // combine/replace with (thisPage/settings) passed in
                _settings = $.extend(_settings, settings);
        
                // will only display if thisPage has a debug var set to true            
                _write('*** DEBUGGER ENABLED ***');             
        
                // do some setup stuff              
        
                // Example to set up interval
                setInterval(
                    function () { _someCheck(); }
                    , _settings.intervalRate
                );
                return this; // allow for chaining of calls to helper  
            };
        
            // sends info to console for module
            var _write = function (text, always) {
                if (always !== undefined && always === true || _settings.debug === true) {
                    console.log(moment(new Date()).format() + ' ~ ' + _helperName + ': ' + text);
                }
            };
        
            // makes the request 
            var _someCheck = function () { 
                // if needed values are in settings
                if (typeof _settings.someAjaxUrl === 'function' 
                    && _settings.variableOne !== undefined) { 
                    $.ajax({
                        dataType: 'json'
                        , url: _settings.someAjaxUrl()
                        , data: {
                            varOne: _settings.variableOne                    
                        }
                        , timeout: _settings.timeout
                    }).done(function (data) {
                        // do stuff
                        _write('Done');
                    }).fail(function (jqxhr, textStatus, error) {                
                        _write('Fail: [' + jqxhr.status + ']', true);
                    }).always(function () {
                        _write('Always');
                    });             
                } else {// if any of the page settings don't exist
                    _write('The module settings do not hold all required variables....', true);            
                }
            };
        
            // Public calls
            return {
                init: _init
            }; 
        
          })();
        

        【讨论】:

        • 我喜欢这个。它简单、标准、没有外部库膨胀。现在我可以将剃刀视图中的 js 代码移动到外部 .ts 文件中的 TypeScript 中,并且仍然可以访问模型变量。完美。
        • 很高兴你喜欢它,我还为外部脚本的示例添加了更多内容。一种模板。这样,我将所有脚本缓存起来,以提高性能并使用出色的剃须刀功能。我只是为每个需要的局部视图创建一个模块。这样一来,一切都很好。
        【解决方案6】:

        您总是可以尝试 RazorJs。它几乎解决了无法在您的 js 文件中使用模型RazorJs

        【讨论】:

          【解决方案7】:

          我遇到了同样的问题,我这样做了:

          查看。

          `var model = @Html.Raw(Json.Encode(Model.myModel));
           myFunction(model);`
          

          外部js。

          `function myFunction(model){
             //do stuff
           }`
          

          【讨论】:

            猜你喜欢
            • 2020-05-07
            • 2013-04-28
            • 2012-03-10
            • 2015-08-02
            • 1970-01-01
            • 2019-05-17
            • 2016-04-21
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多