【问题标题】:KnockoutJs : ko.mapping.fromJS and binding => how to do it properly?KnockoutJs : ko.mapping.fromJS 和 binding => 如何正确执行?
【发布时间】:2020-08-09 02:39:37
【问题描述】:

我真的在为一些我认为很简单的事情而苦苦挣扎......

我正在基于 $.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 是摆脱该错误的绝望尝试。

我尝试了很多东西,但我就是不知道如何正确地做到这一点......

我已经阅读了这个Knockout JS update view from json model 和这个KnockoutJs v2.3.0 : Error You cannot apply bindings multiple times to the same element,但它对我没有多大帮助......也许是因为在加载时没有调用 search() 函数(实际上不应该)。

有哪位高手给我点线索?提前感谢您的帮助!

【问题讨论】:

    标签: data-binding knockout.js mapping


    【解决方案1】:

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

    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>

    【讨论】:

    • 这非常有用和清晰!我不得不进行一些调整,但我想不出更好的答案。非常感谢!
    猜你喜欢
    • 2014-03-22
    • 2014-06-28
    • 2012-10-11
    • 2019-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    相关资源
    最近更新 更多