如何使用 KnockoutJS 通过 AJAX 观察服务器上的数据?
Posted
技术标签:
【中文标题】如何使用 KnockoutJS 通过 AJAX 观察服务器上的数据?【英文标题】:How to use KnockoutJS to observe data on server via AJAX? 【发布时间】:2011-05-22 22:17:03 【问题描述】:我玩过knockoutjs 并生成了以下示例,这足以让我对在 javascript 中构建这些视图模型的想法感到兴奋,以便可以以更简单、声明性的方式编写视图,即首先你定义您想要观察的内容,然后使用data-bind
属性定义当您的视图模型以某种方式发生变化时您想要发生的事情。
但所有这些都只发生在客户端上。
如何扩展此示例以使用 knockoutjs 来观察服务器上对象的状态,例如通过 AJAX 调用?
index.htm:
<!doctype html>
<html>
<title>Knockout example</title>
<head>
<script type="text/javascript" src="js/knockout-1.1.1.debug.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<link rel="stylesheet" href="css/main.css" type="text/css"/>
</head>
<body>
<!-- FIRST AREA -->
<div class="infobox">
<div data-bind="visible: noNamesFilled">
<p>This is an example with NO names filled.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p>This is an example with both names filled.</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p>This is an example with only the first name filled.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p>This is an example with the last name filled but not the first name</p>
</div>
</div>
<!-- SECOND AREA -->
<p>First name: <input data-bind="value: firstName, valueUpdate:'afterkeydown'" /></p>
<p>Last name: <input data-bind="value: lastName, valueUpdate:'afterkeydown'" /></p>
<div data-bind="visible: bothNamesFilled">
<h2 class="normal">Hello, <span data-bind="text: fullName"></span>.</h2>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<h2 class="informal">Hi there <span data-bind="text: fullName"></span>!</h2>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<h2 class="formal">Hello, Mr. <span data-bind="text: fullName"></span>.</h2>
</div>
<!-- THIRD AREA -->
<div data-bind="visible: noNamesFilled">
<p><span class="bad">:-(</span> Please fill in both names.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p><span class="good">:-)</span> Good job, both names are filled!</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p><span class="ok">:-(</span> Please fill in the last name, too.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p><span class="ko">:-(</span> Please fill in the first name as well.</p>
</div>
</body>
</html>
main.css:
* margin: 0; padding: 0
body margin: 10px
p margin: 10px
.infobox
background-color: #eee;
width: 300px;
height: 100px;
padding: 10px;
.informal
color: purple;
font-family: arial;
.normal
color: black;
font-family: new courier;
.formal
color: black;
font-size: 11pt;
font-family: times roman;
background-color: #eee;
.good
width: 20px;
background-color: lightgreen;
.ok
width: 20px;
background-color: yellow;
.bad
width: 20px;
background-color: tomato;
main.js:
window.onload= function()
var viewModel =
firstName : ko.observable(''),
lastName : ko.observable('')
;
viewModel.fullName = ko.dependentObservable(function ()
return viewModel.firstName() + " " + viewModel.lastName();
);
viewModel.bothNamesFilled = ko.dependentObservable(function ()
return viewModel.firstName().length > 0 && viewModel.lastName().length > 0;
, this);
viewModel.firstNameOnlyFilled = ko.dependentObservable(function ()
return viewModel.firstName().length > 0 && viewModel.lastName().length == 0;
, this);
viewModel.lastNameOnlyFilled = ko.dependentObservable(function ()
return viewModel.firstName().length == 0 && viewModel.lastName().length > 0;
, this);
viewModel.noNamesFilled = ko.dependentObservable(function ()
return viewModel.firstName().length == 0 && viewModel.lastName().length == 0;
, this);
ko.applyBindings(viewModel);
【问题讨论】:
【参考方案1】:我会使用 setTimeout 来调用使用 JQuery 进行 $.ajax 调用的函数。当它返回 JSON 数据时,将该数据设置为您的视图模型,最后再次 setTimeout 以调用该函数。
【讨论】:
【参考方案2】:这是一个更新的示例,主要更新 main.js 以与 JQuery 一起执行 ajax 调用。
HTML 文件包含 Knockout 3 而不是 1。HTML 还包含最新的 JQuery 以使 JQuery 功能正常工作。
js/server_data.js 在那里,因此您可以从一些有效的 json 数据开始。您可以将 $.ajax 设置中的 url 更改为您拥有的任何服务器端脚本,但尝试将其内容类型设置为 application/json。例如,php 脚本可以将 Content-type 标头设置为: header('Content-type: application/json');在以 JSON 格式打印数据之前。
新的 main.html:
<!doctype html>
<html>
<title>Knockout example</title>
<head>
<script type="text/javascript" src="js/knockout-3.0.0.debug.js"></script>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<link rel="stylesheet" href="css/main.css" type="text/css"/>
</head>
<body>
<!-- FIRST AREA -->
<div class="infobox">
<div data-bind="visible: noNamesFilled">
<p>This is an example with NO names filled.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p>This is an example with both names filled.</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p>This is an example with only the first name filled.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p>This is an example with the last name filled but not the first name</p>
</div>
</div>
<!-- SECOND AREA -->
<p>First name: <input data-bind="value: firstName, valueUpdate:'afterkeydown'" /></p>
<p>Last name: <input data-bind="value: lastName, valueUpdate:'afterkeydown'" /></p>
<div data-bind="visible: bothNamesFilled">
<h2 class="normal">Hello, <span data-bind="text: fullName"></span>.</h2>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<h2 class="informal">Hi there <span data-bind="text: fullName"></span>!</h2>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<h2 class="formal">Hello, Mr. <span data-bind="text: fullName"></span>.</h2>
</div>
<!-- THIRD AREA -->
<div data-bind="visible: noNamesFilled">
<p><span class="bad">:-(</span> Please fill in both names.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p><span class="good">:-)</span> Good job, both names are filled!</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p><span class="ok">:-(</span> Please fill in the last name, too.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p><span class="ko">:-(</span> Please fill in the first name as well.</p>
</div>
</body>
</html>
js/main.js:
$(document).ready( function()
var viewModel =
firstName : ko.observable(''),
lastName : ko.observable('')
;
viewModel.fullName = ko.dependentObservable(function ()
return viewModel.firstName() + " " + viewModel.lastName();
);
viewModel.bothNamesFilled = ko.dependentObservable(function ()
return viewModel.firstName().length > 0 && viewModel.lastName().length > 0;
, this);
viewModel.firstNameOnlyFilled = ko.dependentObservable(function ()
return viewModel.firstName().length > 0 && viewModel.lastName().length == 0;
, this);
viewModel.lastNameOnlyFilled = ko.dependentObservable(function ()
return viewModel.firstName().length == 0 && viewModel.lastName().length > 0;
, this);
viewModel.noNamesFilled = ko.dependentObservable(function ()
return viewModel.firstName().length == 0 && viewModel.lastName().length == 0;
, this);
ko.applyBindings(viewModel);
// send request to the server to download the server's model information.
$.ajax(
'url': 'js/server_data.js',
'dataType': 'json',
'method': 'post',
'error': function(jqXHR, textStatus, errorThrown)
// error callback in case you play with this code and run into trouble.
alert('There was a problem handling the ajax request. The error information is: jqXHR: '
+jqXHR+", textStatus: "+textStatus+", errorThrown: "+errorThrown);
,
'success': function(data)
// when it is downloaded and parsed to create the "data" parameter, update the viewModel.
viewModel.firstName(data.firstName);
viewModel.lastName(data.lastName);
);
);
js/server_data.js 表示可能来自数据库的动态生成的数据:
"firstName": "John",
"lastName": "Doe"
jsteve 有正确的总体思路,但如果您只想在页面加载时下载数据,请不要使用 setTimeout。相反,请使用 JQuery 的文档就绪回调和 JQuery 的 ajax 成功回调,以便事情在您希望的时候准确运行。
如果您想持续侦听服务器中数据的更改并对其做出反应,请研究长轮询技术。与需要频繁向服务器发出新请求的忙等待相比,长轮询器更有效且计时更准确。
【讨论】:
以上是关于如何使用 KnockoutJS 通过 AJAX 观察服务器上的数据?的主要内容,如果未能解决你的问题,请参考以下文章
knockoutjs:使用 ajax 调用发送 MultipartFile 和其他数据
KnockoutJS,ajax 调用后更新 ViewModel
当页面通过ajax作为部分加载时,如何重新绑定淘汰视图模型?
将 knockoutjs 视图模型传递给多个 ajax 调用