Asp.net mvc4,淘汰赛js,淘汰ViewModel加载所有视图?

时间:2012-09-27 19:21:16

标签: knockout.js asp.net-mvc-4

我是asp.net mvc4和knockoutjs的新手,需要帮助了解视图的工作原理。

  1. 我在共享文件夹中有一个_Layout.vbhtml,它是项目中所有页面的“主”页面。

  2. 我有AccountController,HomeController和GrowerController

  3. 我在Views文件夹中有GrowerController的Grower文件夹。索引是通常的默认视图。

  4. 在Views / Grower / Index中,我有一个从服务器检索数据的knoockout ViewModel。

  5. 现在,当我转到Home / Index等其他视图时,我在Firebug的控制台中看到,即使我不在我创建的视图中,它也会从服务器获取数据淘汰赛ViewModel。

  6. 我很困惑。是否会发生因为我对所有页面使用_layout.vbhtml?我做错了什么?

    修改 *的 _Layout.vbhtml *

        <!DOCTYPE html>
        <html lang="en">
          <head>
           <meta charset="utf-8" />
           <title>@ViewData("Title")</title>
           <meta name="viewport" content="width=device-width" />
           <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
           <link href="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.css" rel="stylesheet" type="text/css" />
    
            @* Javascrips files *@
            <script src="@Url.Content("~/Scripts/knockout-2.1.0.js")" type="text/javascript"></script>
            <script src="@Url.Content("http://code.jquery.com/jquery-1.7.1.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.js")" type="text/javascript"></script>
            <script src="@Url.Content("~/Scripts/custom.js")" type="text/javascript"></script>
    
    
            <!-- Custom stylesheet overriding styles -->
            @If Request.QueryString("pr") = "dow" or ViewData("pr") = "dow" Then
             @<link rel="stylesheet" href="@Url.Content("~/Content/CustomDow.css")" />
            Else
             @<link rel="stylesheet" href="@Url.Content("~/Content/Custom.css")" />
            End If
         </head>
         <body>
           <div data-role="page" data-theme="b">
            <div data-role="header">
                @If IsSectionDefined("Header") Then
                    @RenderSection("Header")
                Else
                    @<h1>@ViewData("Title")</h1>
                    @Html.Partial("_LoginPartial")
                End If
            </div>
            <div data-role="content">
                @RenderBody()
            </div>
        </div>
    
        @RenderSection("scripts", required:=False)
    </body>
    

    种植者/ Index.vbhtml

        @Code
          ViewData("Title") = "Select a Grower/Branch"
        End Code
    
        @section scripts
          <script type="text/javascript">
    
          function SuperViewModel() {
    
            //====== GrowerInfo =======
            var self = this;
            self.GrowerName = ko.observable();
            self.GrowerCompany = ko.observable();
            self.GrowerAddress = ko.observable();
            self.ShowGrowerCompany = ko.observable();
            self.GrowerID = ko.observable();
    
            self.updateGrowerInfo = function () {
              $.getJSON("GetGrower", function (allData) {
              self.GrowerName(allData.Name);
              self.GrowerCompany(allData.CompanyName);
              self.GrowerAddress(allData.Address);
              self.ShowGrowerCompany(allData.ShowCompany);
              self.GrowerID(allData.ID);
             });
            };
    
            //Load initial state from server and populate viewmodel
            self.updateGrowerInfo();
            //========= End GrowerInfo ==========
    
             if ($("#hfFlag").val() == "1") {
              //========= BranchInfo ==========
              self.BranchName = ko.observable();
              self.Company = ko.observable();
              self.Address = ko.observable();
              self.ID = ko.observable();
    
              //Load initial state from server and populate viewmodel
              self.updateBranchInfo = function () {
               $.getJSON("GetBranch", function (allData) {
                self.BranchName(allData.Name);
                self.Company(allData.CompanyName);
                self.Address(allData.Address);
                self.ID(allData.ID);
              });
            };
    
            self.updateBranchInfo();
            //=========== End BranchInfo ==============
          }
    
    
          //=============== GrowerList ===============
          var MyGrower = function (data) {
           this.growerId = ko.observable(data.GrowerId);
           this.growerName = ko.observable(data.GrowerName);
         };
    
          self.growers = ko.observableArray([]);
    
          self.updateGrowers = function () {
            //refresh listview
            $("#ulGrowerList").listview();
            $("#ulGrowerList").listview("refresh");
    
          $.getJSON("GetGrowers", function (allData) {
            var mappedGrowers = $.map(allData, function (item) { return new MyGrower(item) });
            self.growers(mappedGrowers);
    
    
            });
          };
    
          self.setSelectedClassToGrowerList = function (item, event) {
    
            $(ulGrowerList).closest('ul').find('a').removeClass('highlight');
            $(ulGrowerList).closest('ul').find('.selected').remove();
    
            $(event.target).toggleClass("highlight");
            if ($(event.target).hasClass("highlight")) {
              $(event.target).append("<span class='selected'>Selected</span>");
    
              replaceByValue('GrowerID', event.target.id);
              postjsonToServerNow("grower");
    
              //update GrowerInfo 
              $.getJSON("GetGrower", function (allData) {
                self.GrowerName(allData.Name);
                self.GrowerCompany(allData.CompanyName);
                self.GrowerAddress(allData.Address);
                self.ShowGrowerCompany(allData.ShowCompany);
                self.GrowerID(allData.ID);
              });
    
            } else {
              $(event.target).find(".selected").remove();
            }
          };
    
    
    
          self.setSelectedClassToBranchList = function (item, event) {
    
            $(ulBranchList).closest('ul').find('a').removeClass('highlight');
            $(ulBranchList).closest('ul').find('.selected').remove();
    
            $(event.target).toggleClass("highlight");
    
            if ($(event.target).hasClass("highlight")) {
              $(event.target).append("<span class='selected'>Selected</span>");
    
              replaceByValue('BranchID', event.target.id);
              postjsonToServerNow("branch");
            } else {
              $(event.target).find(".selected").remove();
            }
    
          };
    
    
    
          //Load initial state from server and populate viewmodel
          self.updateGrowers();
    
          //============ End GrowerList =============
        }
    
        //============= End ViewModel Section ====================//
    
    
          $(document).bind('pageinit', function () {
            //enable ko
            ko.applyBindings(new SuperViewModel());
    
    
            $("#divBranchList").hide();
    
            //show hide lists
            $("#btnGrower").click(function () {
            $("#divGrowerList").show();
            $("#divBranchList").hide();
           });
    
           $("#btnBranch").click(function () {
             $("#divBranchList").show();
             $("#divGrowerList").hide();
           });
    
          });
        </script>
        End Section
    
    
    
    
        <table class="maintable" id="maintable">
          <tr>
            <td class="left">
              <div id="GrowerInfo">
                <strong>Grower</strong><br />
                <a data-role="button" data-theme="e" id="btnGrower" data-bind="click: updateGrowers">
                  <h3>
                   <span data-bind="text: GrowerName"></span>
                  </h3>
                  <span data-bind="text:GrowerCompany, visible: ShowGrowerCompany" class="block"></span><span data-bind="text: GrowerAddress">
                  </span>
                  <br />
                  <span data-bind="text: GrowerID"></span>
                </a>
              </div>
              @If ViewData("IsDealer") Then
                @<div id="BranchInfo">
                  <strong>Branch</strong> <a data-role="button" data-theme="e" id="btnBranch">
                    <h3>
                      <span data-bind="text: BranchName"></span>
                    </h3>
                    <span data-bind="text: Company"></span>
                    <br />
                    <span data-bind="text: Address"></span>
                    <br />
                    <span data-bind="text: ID"></span></a>
                </div>
              End If
            </td>
            <td class="splitline">
            </td>
            <td class="right">
              <div class="content-right">
                <div id="divGrowerList" style="overflow: auto; height: 450px; padding: 10px;">
    
                <p>Total growers: <span data-bind="text: growers().length">&nbsp;</span></p>
    
                   <ul data-inset="true" data-filter="true" data-bind="foreach: growers" data-role="listview" id="ulGrowerList">
                      <li><a data-bind="click: $parent.setSelectedClassToGrowerList, attr: {id: growerId}"><span data-bind="text: growerName, attr: {id: growerId}, click: $parent.setSelectedClassToGrowerList" /></a></li>
                  </ul>
    
                  <textarea name="growers" rows="10" data-bind="value: ko.toJSON(growers)"></textarea>
    
                </div>
                <div id="divBranchList">
                  @If ViewData("IsDealer") Then
                    @Html.Action("MyBranchList2")
                  End If
                </div>
                @If ViewData("IsDealer") Then
                  @<input type="hidden" id="hfFlag" value="1" />
                Else
                  @<input type="hidden" id="hfFlag" value="0" />
                End If
              </div>
            </td>
          </tr>
        </table>
    

2 个答案:

答案 0 :(得分:0)

没有看到您的_Layout.vbhtml我无法肯定地说,但由于您在每个页面上都运行了javascript,因此您可以在_Layout.vbhtml上使用script标记

因此,请将其移至Index.vbhtml,,将其放入<head>标记,在Layout.vbhtml中使用@RenderSection("Scripts")并在视图中使用:

@Section "Scripts"

@<script>
    // write JS here or reference a file using the src attribute
</script>

End Section

这会将@Section "SectionName"End Section之间的所有内容放在Layout.vbhtml中代替@RenderSection("Scripts")

修改

从你的评论到one.beat.consumer我想我看到了你的问题。但是理解我仍在猜测,因为我没有看到你的代码 - 一个大问题,因为你没有提到你使用的是jQuery Mobile

常规MVC4 Web应用程序和jQuery Mobile应用程序之间存在重大差异。

一个是:使用jQM,您始终位于同一页面上 - 您通过ajax从服务器加载页面,然后将其拆分为<div data-role="page">...</div>。这解释了为什么如果将特定页面的脚本放在<head>部分中,jQM将忽略它们。唯一不会被忽略的<head>部分是原始页面加载的,但并不总是您的主页

因此,要加载特定页面的脚本,您不能使用MVC Sections将其放在<head>元素中。您需要在<div data-role="page">中引用该脚本。 虽然如果你正在缓存你的页面,这只会触发一次,你可能需要绑定到pageshow,如果你想再次触发(可能刷新视图模型)。

最后,

你说你在你的pageinit处理程序中应用了你的viewmodel。每当从服务器获取页面并将其注入DOM时,都会调用此方法。

如果你想让你的js远离视图,你可以在_Layout.vbhtml <head>中引用一个站点范围的js文件(custom.js)并使用:

$(document).on('pageinit', '#PageId', function(event) {
    /* do viewmodel stuff here */
});

只要获取带有<div data-role="page">的{​​{1}}并将其注入DOM,就会运行此操作。您可以在此处使用任何选择器,因此id="PageId"可用于在注入.require-vm的网页时触发。

答案 1 :(得分:0)

您已在_layout页面中定义了Knockout ViewModel。

如果您打算在所有页面上使用此视图模型,这很好,但听起来您不想这样做。将其移动到特定的操作视图中以隔离它。

在您对Sethi的上述评论中,您提到javascripts在您执行此操作时不起作用...这可能是因为您在布局和视图中放置了脚本标记。我敢打赌你正在尝试在加载knockout.js之前构建视图模型。

良好做法:

在您的布局中,将脚本标记放在页面底部,就在</body>关闭标记之前...关闭之前的最后一个标记应该是您的RenderSection()调用设置。

现在,您可以在视图中的任何位置定义此脚本部分,并确保它将在您的框架脚本之后发生 - 例如。 jQuery,Knockout等。

另外,请记住使用jQuery时,最好使用$.ready()来确保脚本仅在加载DOM后运行。