首页 > 解决方案 > 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 调用负载(实际上不应该)。

有哪位高手给我指点一下吗?在此先感谢您的帮助!

标签: data-bindingknockout.jsmapping

解决方案


这就是我将如何接近你想要完成的事情。

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>


推荐阅读