data-binding - KnockoutJs : ko.mapping.fromJS 和 binding => 如何正确执行?
问题描述
我真的在为一些我认为很简单的事情而苦苦挣扎......
我正在基于 $.getJSON 调用制作一个简单的搜索结果表,并希望我的代码尽可能“通用”。
在我的(简化的)HTML 中:
<form id="searchForm">
(...)
<button type="button" onclick="search()">Search</button>
</form>
(...)
<tbody data-bind="foreach: data">
<tr>
<td data-bind="text: FOO"></td>
(...)
<td data-bind="text: BAR"></td>
</tr>
</tbody>
然后在我的 javascript 中(在script
页面下方的标签中):
var search = function(){
var form = $('#searchForm');
$.getJSON("php/query/jsonQuery.php?jsonQuery=search", form.serialize(), function(jsonAnswer, textStatus) {
console.log(jsonAnswer);
if(typeof viewModel === 'undefined'){
var viewModel = ko.mapping.fromJS(jsonAnswer);
ko.applyBindings(viewModel);
}
else{
ko.mapping.fromJS(jsonAnswer, viewModel);
}
$('#divResults').show();
// console.log(viewModel)
});
}
这在第一次“搜索”点击时工作正常......但不是以下 : Error You cannot apply bindings multiple times to the same element
。
你可以猜到,这个非常丑陋的“if”测试 viewModel 是摆脱这个错误的绝望尝试。
我已经尝试了很多东西,但我就是不知道如何正确地做到这一点......
我已经从 json 模型和这个KnockoutJs v2.3.0 阅读了这个 Knockout JS 更新视图:错误你不能多次将绑定应用于同一个元素,但它对我没有多大帮助......也许是因为 search() 函数不是t 调用负载(实际上不应该)。
有哪位高手给我指点一下吗?在此先感谢您的帮助!
解决方案
这就是我将如何接近你想要完成的事情。
var searchService = {
search: function(form, vmData) {
//$.getJSON("php/query/jsonQuery.php?jsonQuery=search", form.serialize(), function(jsonAnswer, textStatus) {
var jsonAnswer = [{
FOO: "Item 1 Foo",
BAR: "Item 1 Bar"
}, {
FOO: "Item 2 Foo",
BAR: "Item 2 Bar"
}]
ko.mapping.fromJS(jsonAnswer, [], vmData);
//})
}
};
var PageViewModel = function() {
var self = this;
self.data = ko.observableArray();
self.hasResults = ko.pureComputed(function() {
return self.data().length > 0;
});
self.search = function() {
var form = $('#searchForm');
searchService.search(form, self.data);
};
};
ko.applyBindings(new PageViewModel());
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<form id="searchForm">
<button type="button" data-bind="click:search">Search</button>
</form>
<div data-bind="visible: !hasResults()"><b>No Results</b></div>
<div data-bind="visible: hasResults">
<table class="table">
<thead>
<tr>
<td>FOO</td>
<td>BAR</td>
</tr>
</thead>
<tbody data-bind="foreach: data">
<tr>
<td data-bind="text: FOO"></td>
<td data-bind="text: BAR"></td>
</tr>
</tbody>
</table>
</div>
<br/>
<pre><code data-bind="text: ko.toJSON($root)"></code></pre>