两种方式的数据绑定不适用于淘汰 Observable Arrays

Posted

技术标签:

【中文标题】两种方式的数据绑定不适用于淘汰 Observable Arrays【英文标题】:Two way databinding is not working with knockout ObservableArrays 【发布时间】:2019-02-05 07:11:02 【问题描述】:

我有以下代码,它有两个功能。

    单击“添加更多”时,将新值推送到可观察数组,将新文本框添加到 UI 点击保存后,在 div 的文本框中显示值。

var model = function() 
  var self = this;
  self.inventoryItems = ko.observableArray();

  myArray = ["Value1", "V1lue2", "Value3", "Value4"];
  self.inventoryItems(myArray);

  self.addItems = function(vm) 
    self.inventoryItems.push('New Item');
  

  self.SaveInventory = function(data) 
    $('#htmlBlock').html(myArray);
    console.log(myArray)
  ;

;

ko.applyBindings(new model());
ul 
  list-style: none;


li 
  margin-top: 5px;


.info-text,
a,
button 
  margin-top: 20px;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<ul data-bind="foreach: inventoryItems">
  <li>
    <input data-bind="value: $data" />
  </li>
</ul>
<div>
  <a data-bind="click: addItems">+ Add more</a>
</div>
<button type="submit" class="btn btn-accent" data-bind="click: SaveInventory">Save changes</button>
<div class='info-text' id="htmlBlock">
</div>

使用此代码,我的 UI 可以正常初始化,当我点击“添加更多”时,能够获得一个新的文本框,并且 myArray/inventoryItems 也可以正常工作。

但是,如果我编辑任何项目并保存值,我将无法取回更新值。

我错过了什么?

【问题讨论】:

@xec,您是否将 $('#htmlBlock') 称为 Vew 代码?这只是为了演示。 谁能解释一下需要改进的地方,不要被否决?我提供了一个 fiddle , sn-p 并解释了我的查询?那么为什么投反对票呢? 不清楚您在问什么。按照一开始的两个步骤,它工作正常。我没有看到您正在苦苦挣扎的是输入字段值本身。我已经更新了我的答案。也可能是因为您连续发布了 4 个非常相似的问题 【参考方案1】:

在可观察数组中不需要单独引用底层数组,它只会混淆事物。使用self.inventoryItems()读出值。

使用带有data-bind="text: ko.toJSON($data, null, '\t')"的元素来实时查看模型外观的好方法

为了进行双向绑定,您需要使每个值(对于输入字段)可观察。通常我会为此使用单独的构造函数。

function EditableField(initialValue) 
  // each value you want to be able to have a two-way binding for needs to be observable
  this.value = ko.observable(initialValue);


var model = function() 
  var self = this;
  self.inventoryItems = ko.observableArray(["Value1", "V1lue2", "Value3", "Value4"].map(function(item) 
    // run each array value through constructor
    return new EditableField(item);
  ));

  self.addItems = function(vm) 
    self.inventoryItems.push(new EditableField('New Item'));
  

  self.SaveInventory = function(data) 
    console.log(ko.toJS(self.inventoryItems)); // fetch the updated array
  ;

;

ko.applyBindings(new model());
ul 
  list-style: none;

li 
  margin-top: 5px;

.info-text,
a,
button 
  margin-top: 20px;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<ul data-bind="foreach: inventoryItems">
  <li>
    <!-- use textInput binding for live updates, bound to the value property from constructor -->
    <input data-bind="textInput: value" />
  </li>
</ul>
<div>
  <a data-bind="click: addItems">+ Add more</a>
</div>
<button type="submit" class="btn btn-accent" data-bind="click: SaveInventory">Save changes</button>

<!-- display the model in real time -->
<pre class='info-text' data-bind="text: ko.toJSON($data, null, '\t')">
</pre>

【讨论】:

谢谢,但是当我在文本框中编辑值并单击保存时,这仍然不会更新值。这是我最初的问题。 非常感谢,ko.observable(initialValue);和 .map 是任何刚开始使用 KO 的人的绝佳指针。我还要记住不要混合 UI 代码 不客气 :) 请注意,.map() 与淘汰赛无关,它是一个原生 javascript 循环。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

以上是关于两种方式的数据绑定不适用于淘汰 Observable Arrays的主要内容,如果未能解决你的问题,请参考以下文章

订阅不适用于淘汰模型作为功能

iCheck 不适用于淘汰赛

淘汰赛和 jQuery 自动完成

Android 数据绑定不适用于 <merge> 属性

Angular 数据绑定不适用于 async/await,但它适用于 Promise

模型绑定不适用于嵌套对象