javascript - 更改数组时 Knockout JS 不更新

标签 javascript knockout.js

我知道这个问题已经被问过多次,但没有一个能回答我的问题。 我有以下内容: 我通过 JSON 将数据转换为 Javascript 并将其转换为二维数组。 当我加载网站时,表格会按需要显示。 现在,当我单击一个按钮(仅用于测试)时,它会更新数组中的一个值并将该数组记录在控制台中,我会在控制台中看到更改后的数组。 问题是更改没有显示在表中。 当我向数组添加一个值时,它会显示在表中。 我做错了什么?

HTML:

<table id="sortsTable">
   <tbody data-bind="foreach: sorts">
   <tr>
     <td data-bind="text: $data.name"></td>
     <td data-bind="text: $data.ingName"></td>
   </tr>
   </tbody>
</table>
<button data-bind="click: addPerson">Add</button>

JS:

var sorts = ko.observableArray([]);

$(function() {
var request = new XMLHttpRequest();
var formData = new FormData();
var responseElements = [];
request.open("POST", "scripts.php", true);
formData.append("action", "getSorts");
request.onreadystatechange = function() {
    if (request.readyState == 4 && request.status == 200) {
        responseElements = JSON.parse(request.responseText);
        sorts = convertList(responseElements);
        ko.applyBindings(new AppViewModel(sorts));
    }
}
request.send(formData);

});

function convertList(response) {  //just the function to convert the json object to a more useful array
    var names = [];
    var ingredients = [];
    var sorts = [];
    for (var index = 0; index < response.length; index++) {
        var name = response[index]['name'];
        var ing = response[index]['ingName'];
        if (names.indexOf(name) == -1) {
            names.push(name);
        }
        if (ingredients.indexOf(ing) == -1) {
            var nameIndex = names.indexOf(name);
            if (ingredients[nameIndex] == undefined) {
                ingredients[nameIndex] = ing;
            } else {
                ingredients[nameIndex] = ingredients[nameIndex] + ", " + ing;
            }
        }
    }
    for (var i = 0; i < names.length; i++) {
        sorts[i] = {};
        sorts[i]['name'] = names[i];
        sorts[i]['ingName'] = ingredients[i];
    }
    return sorts;
}

function AppViewModel(data) {
    var self = this;
    self.sorts = data;
    self.addPerson = function() {
        console.log("click");
        self.sorts[0]["name"] = "test";  //doesn't update table
        //self.sorts.push({name: "qwer", ingName: "we"});  //works like expected
        console.log(self.sorts);
    };
}

谢谢。

最佳答案

observable 数组只监控哪些项目被添加到它,而不是项目本身,所以

self.sorts.push({name: "qwer", ingName: "we"});  //works like expected

之所以有效,是因为您正在获取要添加到其项中的可观察数组,但是

self.sorts[0]["name"] = "test";  //doesn't update table

不起作用,因为可观察数组无法知道其中的项目已更改。为此,数组中项目的属性需要是可观察的。

在 convertList 中切换到:

for (var i = 0; i < names.length; i++) {
    sorts[i] = {};
    sorts[i]['name'] = ko.observable(names[i]);
    sorts[i]['ingName'] = ko.observable(ingredients[i]);
}

而且它们必须通过调用可观察的 setter 方法来设置,如下所示:

self.addPerson = function() {
    console.log("click");
    self.sorts[0]["name"]("test");
    ...

顺便说一句,您这里似乎还有一些其他问题。您在第一行将 sorts 定义为可观察数组,但您用 convertList 的返回值覆盖它,这是一个普通数组,而不是可观察数组。

sorts = convertList(responseElements);
ko.applyBindings(new AppViewModel(sorts));

我会删除第一行并将排序创建为可观察数组

function convertList(response) {  //just the function to convert the json object to a more useful array
    var names = [];
    var ingredients = [];
    var sorts = ko.observableArray([]);
    ...

关于javascript - 更改数组时 Knockout JS 不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42809900/

相关文章:

javascript - Jquery:如何检查元素是否具有特定的 css 类/样式

knockout.js - knockout 验证首次阻止点击处理程序

javascript - knockout js : Code to bind an object rather than individual values

javascript - 在悬停时打开下拉菜单切换 - knockout

javascript - 在 Google Chrome 中检查 jsfiddle.net 上的 javascript

JavaScript:如何将此 utc 日期时间字符串转换为本地时间

javascript - 有人可以解释一下这个回文解决方案吗?

javascript - `element.next().insertBefore(element)` 是做什么的?

javascript - 如何从 Knockout.js 的复选框列表中只选择一个复选框

javascript - Knockout - 自定义绑定(bind) - 将变量从 init 传递到 update