Обновление Knockout.js, наблюдаемого из JSON - PullRequest
12 голосов
/ 02 апреля 2012

Я пытаюсь установить сетку и обновить ее с помощью большего количества записей через 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]);
      };   

Ответы [ 3 ]

22 голосов
/ 02 апреля 2012

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

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

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

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

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) Создайте свою собственную функцию в массиве observableArray, например:

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 голосов
/ 02 апреля 2012

Вы можете использовать плагин mapping

См. http://knockoutjs.com/documentation/plugins-mapping.html

1 голос
/ 31 января 2017

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

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

Пример в JsFiddle

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

...