2013-07-04 100 views
6

我只是用MVC-Web-API調查knockout.js,並試圖創建一個Hello World頁面,每隔5秒更新一次頁面上的時間。它每5秒發出一次呼叫,我可以在我的控制器(斷點)中看到這一點,但屏幕上仍然沒有顯示。Knockout.js - 每5秒更新一次新頁面的值

更新: 我一直在努力,我現在已經確定我從服務器獲取數據,每5秒向控制器發出一次呼叫,並且它正在返回JSON I需要(警報顯示此),但頁面上的span元素上仍然沒有顯示。

我實際上需要使用映射函數,因爲我正在開發一個更大的網站,該網站擁有超過50個屬性的模型,並且不特別想要通過並將它們分別映射到視圖模型中。

我在下面列入了我的代碼。

<span data-bind="text: TimeString"></span> 

<script type="text/javascript"> 
    var viewModel; 
var getUpdates = setInterval(function() { 
    $.getJSON(
     "/Values/Get", {}, 
     function (model) { 
      alert(model.TimeString); 
      ko.mapping.fromJS(model, viewModel); 
     }); 
}, 5000); 

$(document).ready(
    function() { 
     $.getJSON(
      "/Values/Get", {}, 
      function (model) { 
       var viewModel = ko.mapping.fromJS(model); 
       alert(model.TimeString); 
       ko.applyBindings(viewModel); 
      }); 
    }); 

function bindViewModel(model) { 
    ko.applyBindings(model); 
} 

public class HelloWorldModel 
{ 
    public DateTime TimeDT { get; set; } 
    public String TimeString { get; set; } 
} 

    public class ValuesController : Controller 
{ 
    public HelloWorldModel Model = new HelloWorldModel(); 

    [System.Web.Mvc.AcceptVerbs(HttpVerbs.Get)] 
    public JsonResult Get() 
    { 
     Model.TimeDT = DateTime.Now; 
     Model.TimeString = Model.TimeDT.ToString("HH:mm:ss"); 

     return Json(Model, JsonRequestBehavior.AllowGet); 
    } 

    // POST api/values 
    public void Post([FromBody]string value) 
    { 
    } 

    // PUT api/values/5 
    public void Put(int id, [FromBody]string value) 
    { 
    } 

    // DELETE api/values/5 
    public void Delete(int id) 
    { 
    } 
} 
} 
+0

綁定中的數據是什麼?它是一個自定義綁定?或者你的意思是''? – nemesv

+0

updateFromJSON從哪裏來?在文檔中,它聲明'ko.mapping.fromJS(data,viewModel);' – Peter

+0

您應該在原始的AJAX調用中使用映射插件,而不是每5秒重複一次。 –

回答

6

如果按照documentation,應該不會太難。在你第一次調用服務器,這樣做:

var viewModel = ko.mapping.fromJS(model); 
ko.applyBindings(viewModel); 

你申請綁定一個JS對象(的getJSON會返回一個JS對象,而不是一個JSON字符串,如果我正確讀the documentation)。

之後,在你的重複功能,這樣做:

ko.mapping.fromJS(model, viewModel); 

從文檔:

  • 對象的所有屬性都轉換成可觀察到的。如果更新會更改該值,則會更新可觀察值。數組轉換爲可觀察數組。如果更新會更改項目數量,則會執行相應的添加/刪除操作。它還會嘗試將訂單保留爲原始的 JavaScript數組。
4

你不需要更換整個視圖模型而是可以更新屬性從Ajax請求返回,就像這樣:

$(function() { 
    var vm = { 
     TimeDT: ko.observable(), 
     TimeString: ko.observable() 
    }; 

    function updateValues() {  
     $.getJSON("/Values/Get").done(function(data) { 
      vm.TimeDT(data.TimeDT); 
      vm.TimeString(data.TimeString); 
     }); 
    } 

    ko.applyBindings(vm); 

    updateValues(); 
    setInterval(updateValues, 5000); 
}); 

這裏你可以看到一個small example我在做的jsfiddle。

+0

的確如此,他並不需要完全取代viewmodel。但有了這個解決方案,你又可以自己完成所有的工作。關於KO映射插件的好處是,這對你來說是這樣。第一次(當創建viewmodel的時候),以及後來當你想更新你的viewmodel的時候。它會爲你更新所有觀測值(用'ko.mapping.fromJS(model,viewModel);')。當你有幾個可觀察的屬性,以及隨着時間的推移添加屬性時,這很有趣。 – Peter

+0

是的,我也同意你的看法。在這種情況下,我會讓他當前的ViewModel成爲更復雜(合成的)ViewModel的屬性。我發佈的答案適用於簡單的場景,比如Ben在他的例子中發佈的一個場景。 – Meryovi

3

聲明:我與Ben合作。

代碼有幾個問題,第一個是缺少一些javascript引用,第二個viewModel對象每次定時器循環時都是空的。

您需要從here下載挖空映射JavaScript文件,將其命名爲knockout.mapping-latest.js並將其保存在Scripts目錄中。然後確保添加了對jquery和knockout.js的引用。

更新的Razor視圖低於:

<div id="body"> 

    <span data-bind='text: TimeString'></span> 

    <script src="~/Scripts/jquery-1.8.2.js" type="text/javascript"></script> 
    <script src="~/Scripts/knockout-2.2.0.debug.js" type="text/javascript"></script> 
    <script src="~/Scripts/knockout.mapping-latest.js" type="text/javascript"></script> 
    <script type="text/javascript"> 
     var viewModel; 
     var getUpdates = setInterval(function() { 
      $.getJSON(
       "/Values/Get", {}, 
       function (model) { 
        //alert(model.TimeString); 
        ko.mapping.fromJS(model, viewModel); 
       }); 
     }, 5000); 

     var viewModelSet = false; 

     $(document).ready(
      function() { 
       $.getJSON(
        "/Values/Get", {}, 
        function (model) { 
         viewModel = ko.mapping.fromJS(model); 
         ko.applyBindings(viewModel); 
        }); 
      }); 

     function bindViewModel(model) { 
      ko.applyBindings(model); 
     } 
    </script>  

</div> 

我想補充,公共領域中的一類,一般一個不走,在你的視圖模型您HelloWorldModel情況沒有得到來自其他任何地方訪問代碼,只是在該類內部,因此它可以是私有的。如果從其他地方訪問,最好的做法是保持私密性,並通過財產進行披露。更多信息here