我只是在使用MVC-Web-API查看knockout.js,我正在尝试创建一个Hello World页面,它将每5秒更新页面上的时间。它每隔5秒拨打一次电话,我可以在我的控制器(断点)中看到这个,但屏幕上仍然没有显示。
更新: 我一直在研究这个问题,现在我已经确定我从服务器获取数据,每5秒钟调用一次控制器,它返回我需要的JSON(警报显示这个)但是页面上的span元素上仍然没有显示任何内容。
我实际上需要使用映射功能,因为我正在开发一个更大的网站,它拥有一个包含50多个属性的模型,并且不特别想要在viewmodel中单独映射它们。
我在下面提供了我的代码。
<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 :(得分:6)
如果你遵循documentation,那就不应该太难了。在第一次调用服务器时,请执行以下操作:
var viewModel = ko.mapping.fromJS(model);
ko.applyBindings(viewModel);
您正在使用JS对象应用绑定(如果我正确阅读the documentation,则getJSON返回JS对象,而不是JSON字符串。)
之后,在您的重复功能中,执行:
ko.mapping.fromJS(model, viewModel);
来自文档:
- 对象的所有属性都将转换为可观察对象。如果更新会更改值,则会更新observable。
- 将数组转换为可观察数组。如果更新会更改项目数,则会执行相应的添加/删除 动作。它还会尝试保持订单与原始订单相同 JavaScript数组。
答案 1 :(得分: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);
});
你可以在这里看到我在JsFiddle中制作的small example。
答案 2 :(得分:3)
免责声明:我与Ben合作。
代码存在一些问题,第一个是缺少一些javascript引用,其次,每次定时器循环时,viewModel对象始终为null。
您需要从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>
只是要添加,类中的公共字段通常是禁止的,在您的ViewModel中,您的HelloWorldModel实例无法从代码中的任何其他位置访问,只能从该类中访问,因此它可以是私有的。如果从其他地方访问它,最好的做法是将其保密,并通过属性公开。更多信息here。