Knockout JS在更改数组时不会更新

时间:2017-03-15 12:34:09

标签: javascript knockout.js

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

HTML:

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);
    };
}

JS:

GoogleChart

感谢。

2 个答案:

答案 0 :(得分:2)

可观察数组仅监视添加到其中的项目,而不是项目本身,所以

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([]);
    ...

答案 1 :(得分:2)

问题是当你绑定它时:

 <td data-bind="text: $data.name"></td>

$data.name不可观察,它是一个对象的简单属性,在这里创建:

sorts[i]['name'] = names[i];

Knockout会非常高兴地绑定这样的属性并显示它们,但是对它们的任何更新都不会被淘汰。相反,除了observableArray之外,您还需要创建您希望能够更新可观察对象的任何单个属性:

sorts[i]['name'] = ko.observable(names[i]);

然后当你更新它时,淘汰赛会看到变化。但是请注意,你不能简单地只分配给属性,因为你只是覆盖了敲掉的observable并且它会丢失,而你需要用更新调用 observable:

self.sorts[0]["name"]("test");