Обновление Knockout.js Наблюдается от JSON

Я пытаюсь создать сетку и обновить ее с помощью большего количества записей через JSON. В этом простом примере я могу достичь требуемой функциональности, но я могу только обновить/нажать одну запись JSON. Я хотел бы иметь возможность добавлять несколько записей через JSON? Как я мог это достичь? Я предположил, что мне, возможно, придется создать какой-то цикл for и подтолкнуть каждый результат JSON к наблюдаемому, но я надеялся, что у нокаута может быть лучший способ обновления/синтаксического анализа через JSON?

Вот копия того, что я до сих пор добился: http://jsfiddle.net/sparkhill/crSbt/

     function Users(user_id, password) {
    this.user_id = ko.observable();
    this.password = ko.observable();
}

var viewModel = {

    users: ko.observableArray([]),


    addUser: function () {
        this.users.push({

            user_id: "",
            password: ""
        });
    },

    addJSON: function () {


        //Works Fine
        var JSONdataFromServer
        ='{"user_id":"frances","password":"password"}';

        //More than one result - wont map - Would Ideally like to map lots of records at one time
//var JSONdataFromServer ='{"user_id":"frances","password":"password"}, {"user_id":"frances","password":"password"}';

        var dataFromServer = ko.utils.parseJson(JSONdataFromServer);


        this.users.push(dataFromServer);

         //Tried
        //this.users.push(JSON.parse(JSONdataFromServer));


    }

};

viewModel.users();
ko.applyBindings(viewModel);

    </script> 

Обновление, похоже, работает, но я задаюсь вопросом, является ли это более эффективным методом?

addJSON: function () {

        //Works Fine
        var JSONdataFromServer
        ='[{"user_id":"frances","password":"password"},{"user_id":"timmy","password":"password"}]';

        var results = JSON.parse(JSONdataFromServer);

        var i = results.length;

        for(var i = 0; i < results.length; i++){

            this.users.push(results[i]);
      };   

Ответ 1

Вот три способа, которыми вы могли бы это сделать: найти в этой скрипте: http://jsfiddle.net/johnpapa/nfnbD/

1) Используйте функцию ko.utils.arrayPushAll 2) используйте свою собственную логику 3) Напишите свою собственную функцию на наблюдаемом массиве

Подробнее...

1) Если вы используете функцию ko.utils.arrayPushAll, вам также нужно будет вызвать значениеHasMutated, потому что массив эффективно перезаписывается самим. Наблюдаемость не срабатывает, если вы говорите, что она изменилась. Вот как вы могли это сделать:

ko.utils.arrayPushAll(this.users(), dataFromServer);
this.users.valueHasMutated();

2) Второй вариант - написать собственную логику цикла, по существу используя тот же код, что и функция arrayPushAll.

for (var i = 0, j = dataFromServer.length; i < j; i++)
this.users.push(dataFromServer[i]);

3) Создайте собственную функцию в наблюдаемом массиве, например:

ko.observableArray.fn.pushAll = function(valuesToPush) {
        var items = this;
        for (var i = 0, j = valuesToPush.length; i < j; i++){
            items.push(valuesToPush[i]);
        }
        return items;
};

Хотя этот код выше будет уведомлять каждый раз, когда элемент добавляется. Поэтому было бы лучше добавить их все, а затем уведомить. Это было бы более эффективно. Вот так:

ko.observableArray.fn.pushAll = function(valuesToPush) {
    var underlyingArray = this();
    this.valueWillMutate();
    ko.utils.arrayPushAll(underlyingArray, valuesToPush);
    this.valueHasMutated();
    return this;
};

Затем назовите его следующим образом:

this.users.pushAll(dataFromServer);

Ответ 3

Я знаю, что это довольно старая статья, но я наткнулся на нее и просто подумал, что я покажу еще один способ сделать это в нокауте, не создавая свой собственный pushAll для будущих посетителей.

Вы можете использовать push.apply в нокауте на наблюдаемом массиве. Это позволит вам нажимать несколько элементов с сервера и вызывать только одно уведомление.

Пример в JsFiddle

Изменить: дальнейшее чтение для тех, кто читает это, кто хочет знать, почему использовать push.apply вместо этого использования push в цикле