将JavaScript放在部分视图中是否可以

时间:2012-06-19 09:32:09

标签: javascript asp.net-mvc razor partial-views

我正在使用主页面包含两部分的网络应用程序:始终可见的常量块和由3个部分视图之一组成的信息块。每个部分视图都作为AJAX请求的结果出现,并且只加载一次(在jquery提供切换窗口之后)。它运作良好,但我遇到了一个问题。

部分视图的html代码包含在常量块和info-block中使用的js函数。当页面加载时,这些函数可以“看到”彼此并且它可以工作,但是resharper找不到函数声明并警告我这一点。我无法通过将它们转移到外部js文件来解决问题,因为razor语法可以在他们的代码中找到。

我该怎么办?

感谢。

更新

最后,我决定解决将js代码与视图分离的问题。所以新的问题是如何将razor语法包含到js文件中或者什么是可接受的替代方案。我发现的流行解决方案是使用全局变量,数据属性和我更喜欢的解决方案 - John Katsiotis的RazorJS库。

http://djsolid.net/blog/razorjs---write-razor-inside-your-javascript-files

我希望它能稳定运行并让Resharper高兴。

干杯!

更新

3年后,我回忆起这个问题,并决定根据我的经验对其进行更新。事实上,现在我宁愿不建议使用额外的库。特别是如果您不是项目团队中唯一的成员......如果您在所有库中得到保证,它们会受到创建者和社区的支持,并且可以轻松集成到您的IDE中(例如,如果使用特殊语法) 。你的团队中的所有人都应该知道它是如何工作的。所以现在我建议做下面的事情:

  1. 将所有JS保存在单独的文件中。尽可能地隔离它。 为它提供外部API。
  2. 从您的视图中调用API函数。
  3. 将所有Razor生成的URL,文本消息,常量作为资源参数传递。
  4. 例如:

    js file:

    $.api.someInitFunction = function(resources){ ... }
    

    查看:

    <script>
        $.api.someInitFunction({
            urls: { myAction: '@Url.Action("MyAction", "MyController")' },
            messages: { error: '@errorMessage' },
            consts: { myConst: @myIntConst }
        });
    </script>
    

5 个答案:

答案 0 :(得分:30)

如果Resharper警告你,这不是什么大问题^ _ ^

但如果我是你,我就不会将JavaScript放在局部视图中

由于部分视图可以多次插入一个页面,因此您的JavaScripts会出现问题。

对于您的情况,如果您无法将JavaScript与JS文件分开,那么只需创建另一个PartialView并将这些脚本放入其中,然后只在主页中呈现它。

答案 1 :(得分:6)

如果要编写封装了“小部件”的部分视图,只要将它们包含在页面中就可以正常工作,那么在部分视图中嵌入脚本块是将标记和初始化脚本包装在一起的一种简洁方法。部分观点。例如,我可能有一个名为“_EventList”的部分视图,我在整个网站中使用它。如果我放在我的母版页上的两个位置它应该工作,我不想在我的母版页中编写逻辑来初始化小部件。

如果您在页面中不会多次使用它,那么它很简单。但如果可能的话,请将脚本包装起来,使其不会执行两次。见下文。为了Stack Overflow片段,我通过在代码片段中重复两次局部视图来模拟它,以表示在母版页中包含两次局部视图。

我的母版页可能如下所示:

<div id="left-nav">
   @Html.Partial("_EventList")           
</div>

<div id="body">
</div>

<div id="right-nav">
   @Html.Partial("_EventList")
</div>

示例:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<!-- Self-contained partial view containing widget -->

<div id="widgetDiv" class="panel panel-default">

    <div class="panel-heading">Event Dates</div>
    <div class="panel panel-group">
       <ul class="widget">
         <!-- These will load dynamically -->
       </ul>
    </div>

    <script>
        $(document).ready(function() {

            // Run this once only in case widget is on page more than once
            if(typeof $widget == 'undefined') {
                $widget = $("ul.widget"); // could be more than one
                // mock data to simulate an ajax call
                var data = [
                   {Description: "March", StartDate: "03/01/2015"},
                   {Description: "April", StartDate: "04/01/2015"},
                   {Description: "May", StartDate: "05/01/2015"}
                ];

                $.each($widget, function(w, widget) {
                    // might be an $.ajax call
                    $.each(data, function(i, row) {
                        $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>");
                    });
                });
            }
        });
    </script>
</div>
<!-- End of widget / partial view -->



<!-- Second copy of above for sake of example snippet -->
<!-- No need to read further -->









<!-- Self-contained partial view containing widget -->

<div id="widgetDiv" class="panel panel-default">

    <div class="panel-heading">Event Dates</div>
    <div class="panel panel-group">
       <ul class="tinylist nav nav-sidebar widget">
         <!-- These will load dynamically -->
       </ul>
    </div>

    <script>
        $(document).ready(function() {

            // Run this once only in case widget is on page more than once
            if(typeof $widget == 'undefined') {
                $widget = $("ul.widget"); // could be more than one
                // mock data to simulate an ajax call
                var data = [
                   {Description: "March", StartDate: "03/01/2015"},
                   {Description: "April", StartDate: "04/01/2015"},
                   {Description: "May", StartDate: "05/01/2015"}
                ];

                $.each($widget, function(w, widget) {
                    // might be an $.ajax call
                    $.each(data, function(i, row) {
                        $(widget).append("<li><a href='/Widget/Search?startDate=" + row.StartDate + "'>" + row.Description + "</a></li>");
                    });
                });
            }
        });
    </script>
</div>
<!-- End of widget / partial view -->

答案 2 :(得分:3)

我同意Wahid的观点,即你不应该在所有部分或其他方面将JavaScript放入视图中。我已经看到了足够的代码,知道它只会导致无益。

我还要说你应该能够将Razor语法中封装的逻辑转移到JavaScript中,你只需要将你逻辑所需的信息传递给你。

我只是猜测下一条评论的经验,但你应该像设计C#或VB.NET代码的结构一样设计JavaScript。这样你使用Razor的逻辑应该是你的JavaScript的一部分。

这样你的JavaScript将更容易维护,我认为Resharper也应该更快乐。

答案 3 :(得分:2)

我这样做,发现非常方便。它适用于动态加载部分javascript片段以及ViewBag,HttpContext等的可用性。

它产生的感觉就像使用T4模板。

如果你添加像这样的幻像脚本标签,你甚至可以获得javascript验证,智能感知等。

@using System.Configuration
@if (false)
{
    @:<script type="text/javascript">
}    
        $scope.clickCartItem = function(cartItem) {
            console.log(cartItem);
            window.location.href =@Html.Raw("('" + ConfigurationManager.AppSettings["baseUrl"] + "/Checkout/' + cartItem.ItemId)");
        };
        dataAccess.getCart(
        function (response) {
            //...
        },
        function (response) {
            //...
        }
        );

@if (false)
{
    @:</script>
}

答案 4 :(得分:0)

对于这个问题的未来观看者,这是我的经验。我认为将仅供部分使用的脚本保留在用于组织的部分中是一个好主意。

我在调试过程中遇到的问题,有时我很难碰到断点,除非将脚本移至父视图,否则无法解决问题。最有可能是由于多次打印该功能。我希望各节可以更好地解决和组织此问题,但部分视图不支持各节(至少在MVC 4中不支持)。

因此,我的回答是出于维护和调试的目的,不应将任何脚本放入局部视图中。