javascript 从 observableArray-knockoutjs 中移除

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12201010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:33:57  来源:igfitidea点击:

remove from observableArray- knockoutjs

javascriptasp.net-mvcknockout.js

提问by Mr Jones

I'm sure this will be an easy answer for somebody. I have the following ViewModel:

我相信这对某人来说是一个简单的答案。我有以下视图模型:

@{
    var initialData = new JavaScriptSerializer().Serialize(Model);
}
var data = @Html.Raw(initialData);
function ViewModel(data) {
    var self = this;
    self.Name = ko.observable(data.Name);
    self.Items = ko.observableArray(data.Items);
    self.addItem = function() { self.Items.push(""); };
    self.removeItem = function(data) { self.Items.remove(data); }
}
$(document).ready(function() {ko.applyBindings(new ViewModel(data)); });

And the following View:

以及以下视图:

<div>
    Name: <span data-bind="text: Name"></span>
</div>
<div>
    Items: <button data-bind="click: addItem">Add Item</button>
</div>
<div>
    <table>
        <tbody data-bind="template: { name: 'itemTemplate', foreach: Items }"></tbody>
    </table>
</div>
<script type="text/html" id="itemTemplate">
    <tr>
        <td>
            <input data-bind="value: $data" />
            <a href="#" data-bind="click: function() {$parent.removeItem($data)}">Remove Item</a>
        </td>
    </tr>
</script>

Everything seems to work correctly except for removeItem. When new rows have been added, and "Remove Item" is clicked on an empty new row, all of the new rows will be removed with it. I've looked at tons of knockout tutorials trying to get this to work, and my method seems to be a valid attempt, but obviously... I must be missing something. Any suggestions?

除了removeItem. 添加新行并在空的新行上单击“删除项目”后,所有新行都将随之删除。我已经查看了大量的淘汰教程,试图让它发挥作用,我的方法似乎是一个有效的尝试,但显然......我一定错过了一些东西。有什么建议?

回答by RP Niemeyer

The removefunction of an observableArray loops through the array and deletes any items that match the value passed to it. In your case, you are just dealing with strings and it will see that all of the new ones (with no value) will match "".

removeobservableArray的函数循环遍历数组并删除与传递给它的值匹配的任何项目。在您的情况下,您只是在处理字符串,它会看到所有新字符串(没有值)都将匹配“”。

There are a couple ways to handle it:

有几种处理方法:

  • you can deal with objects instead of just strings like { value: ko.observable("") }. Then, when you pass $datait will only delete the actual item that matches that object reference. If your value is not observable and is the data itself (not a property), then your writes won't actually make it back to your view model.

  • if that does not work for your scenario, then you could delete items based on the index ($index) using splice.

  • 您可以处理对象,而不仅仅是像{ value: ko.observable("") }. 然后,当您传递$data它时,它只会删除与该对象引用匹配的实际项目。如果您的值不可观察并且是数据本身(不是属性),那么您的写入实际上不会将其返回到您的视图模型。

  • 如果这不适用于您的场景,那么您可以$index使用 splice.dat删除基于索引 ( ) 的项目。

I would probably do it like: http://jsfiddle.net/rniemeyer/N3JaW/

我可能会这样做:http: //jsfiddle.net/rniemeyer/N3JaW/

Also note that the event(clickis a wrapper to event) binding will pass the current data as the first argument to the handler, so you can simplify your binding to click: $parent.removeItem.

另请注意,event(click是 to 的包装器event) 绑定会将当前数据作为第一个参数传递给处理程序,因此您可以将绑定简化为click: $parent.removeItem

Update: here are several ways that you can control how your object is converted to JSON:

更新:您可以通过以下几种方式控制对象转换为 JSON 的方式:

  • ko.toJSONpasses its 2nd and 3rd arguments on to JSON.stringify. The second arg let's you run a function to potentially replace values as described here. Here is a sample that checks to see if the key is a number (array item) and it has a valueproperty. If so, it just returns the string rather than the object. http://jsfiddle.net/rniemeyer/N3JaW/1/

  • If you use a constructor function for your objects, then you can override the toJSONfunction as described here. Here is your sample with this functionality: http://jsfiddle.net/rniemeyer/N3JaW/2/

  • Another technique that can be used is to maintain a computed observable that has the "good" value. Here is sample: http://jsfiddle.net/rniemeyer/N3JaW/3/. In this one Itemsis a computed observable that returns the clean value. Items.asObjectscontains the object version of your values. When converted to JSON, the asObjectspart is naturally dropped when Itemsis converted to JSON. If you only need this "good" array when converting to JSON, then the other options are better for performance (they only are calculated when you want to send it).

  • ko.toJSON将其第二个和第三个参数传递给JSON.stringify. 第二个参数让您运行一个函数来潜在地替换此处描述的值。这是一个示例,用于检查键是否为数字(数组项)并且是否具有value属性。如果是这样,它只返回字符串而不是对象。 http://jsfiddle.net/rniemeyer/N3JaW/1/

  • 如果您为对象使用构造函数,则可以toJSON按照此处所述覆盖该函数。这是具有此功能的示例:http: //jsfiddle.net/rniemeyer/N3JaW/2/

  • 另一种可以使用的技术是维护一个具有“好”值的计算出的 observable。这是示例:http: //jsfiddle.net/rniemeyer/N3JaW/3/。在这个Items是一个计算的 observable,它返回干净的值。 Items.asObjects包含您的值的对象版本。当转换为JSON时,该asObjects部分在Items转换为JSON时自然会被删除。如果您在转换为 JSON 时只需要这个“好”数组,那么其他选项对性能更好(它们仅在您想要发送时计算)。