Підпишіться на спостережуваний масив лише для нових або видалених записів


75

Так що так, я можу підписатися на спостережуваний масив:

vm.myArray = ko.observableArray();
vm.myArray.subscribe(function(newVal){...});

Проблема полягає в newValтому, що функція передає весь масив. Чи можу я все-таки отримати лише дельту? Скажіть доданий чи видалений елемент?

Відповіді:


126

Починаючи з KnockoutJS 3.0, на ko.observableArray є опція підписки arrayChange.

var myArray = ko.observableArray(["Alpha", "Beta", "Gamma"]);

myArray.subscribe(function(changes) {

    // For this example, we'll just print out the change info
    console.log(changes);

}, null, "arrayChange");

myArray.push("newitem!");

У наведеному вище зворотному виклику аргументом changes буде масив об’єктів змін, подібних до цього:

[ 
   { 
      index: 3, 
      status: 'added', 
      value: 'newitem!' 
   }
]

Що стосується вашої конкретної проблеми, ви хочете отримувати сповіщення про нові або вилучені елементи . Щоб реалізувати це за допомогою Knockout 3, це виглядатиме так:

myArray.subscribe(function(changes) {

    changes.forEach(function(change) {
        if (change.status === 'added' || change.status === 'deleted') {
            console.log("Added or removed! The added/removed element is:", change.value);
        }
    });

}, null, "arrayChange");

1
який статус має «модифікована» особа?
beauXjames

Я не розумію, про що ви запитуєте, коли говорите: "модифікована особа".
Джуда Габріель Хіманго

індивідуальний == екземпляр змін == change ['додано', 'видалено', '???', '???', ... ???]
beauXjames

2
Якщо ви запитуєте, що таке сповіщення, якщо окремий елемент був змінений, один із елементів масиву, відповідь - ні. Ви отримуватимете повідомлення лише про видалення та доповнення.
Джуда Габріель Хіманго

4
документація вказує, що переміщувані елементи також будуть сигналом про додану або видалену зміну, myArray.reverse(); // [{ index: 0, moved: 1, status: 'deleted', value: 'Alpha' },{ index: 1, moved: 0, status: 'added', value: 'Alpha' }] можливо, має бути перевірка на доданий і видалений статус без властивості переміщення?
Пол

7

Оскільки я не міг знайти ніякої інформації про це в іншому місці, я додаю відповідь про те, як використовувати це з TypeScript.

Ключовим тут було використання інтерфейсу KnockoutArrayChange як TEvent для передплати. Якщо ви цього не зробите, він спробує використати іншу (не загальну) підписку та скаржиться на статус, індекс та значення, які не існують.

class ZoneDefinition {
    Name: KnockoutObservable<String>;
}

class DefinitionContainer
{
    ZoneDefinitions: KnockoutObservableArray<ZoneDefinition>;
    constructor(zoneDefinitions?: ZoneDefinition[]){
        this.ZoneDefinitions = ko.observableArray(zoneDefinitions);
        // you'll get an error if you don't use the generic version of subscribe
        // and you need to use the KnockoutArrayChange<T> interface as T
        this.ZoneDefinitions.subscribe<KnockoutArrayChange<ZoneDefinition>[]>(function (changes) {
            changes.forEach(function (change) {
                if (change.status === 'added') {
                    // do something with the added value
                    // can use change.value to get the added item
                    // or change.index to get the index of where it was added
                } else if (change.status === 'deleted') {
                    // do something with the deleted value
                    // can use change.value to get the deleted item
                    // or change.index to get the index of where it was before deletion
                }
            });
        }, null, "arrayChange");
}

1

Для того, щоб виявляти лише події push()та remove()події, а не переміщувати елементи, я розмістив обгортку навколо цих спостережуваних функцій масиву.

var trackPush = function(array) {
    var push = array.push;
    return function() {
        console.log(arguments[0]);
        push.apply(this,arguments);
    }
}
var list = ko.observableArray();
list.push = trackPush(list);

Оригінальна функція push зберігається в закритті, потім накладається на обгортку, яка дозволяє мені робити все, що завгодно, із натиснутим елементом до або після того, як він буде висунутий на масив.

Подібний зразок для remove().


0

Я використовую подібний, але інший підхід, відстежуйте, чи був елемент інструментований в самому елементі:

myArray.subscribe(function(array){
  $.each(array, function(id, el) {
    if (!el.instrumented) {
      el.instrumented = true;
      el.displayName = ko.computed(function(){
        var fn = $.trim(el.firstName()), ln = $.trim(el.lastName());
        if (fn || ln) {
          return fn ? (fn + (ln ? " " + ln : "")) : ln;
        } else {
          return el.email();
        }
      })
    }
  });
})

Але це справді нудно, і шаблон повторюється в моєму коді


Щоб врятувати собі майно, ви можете використати: if (! ('DisplayName' in el)) {}
GrantDG

-1

Жодного, про який я знаю. Хочете знати, що я роблю? Я використовую попередню змінну, щоб утримувати значення, що називаєтьсяselectedItem

vm.selectedItem = ko.observable({});
function addToArray(item) { vm.selectedItem(item); vm.myArray.push(item); }

Отже, коли щось трапляється з моїм спостережуваним масивом, я знаю, який елемент був доданий.

vm.myArray.subscribe(function(newArray) { var addedItem = vm.selectedItem(item); ... }

Це справді багатослівно, і якщо припустити, що ваш масив містить багато видів даних, вам потрібно буде мати певні прапори, які допоможуть вам знати, що робити зі збереженими змінними ...

vm.myArray.subscribe(function(newArray) {
  if ( wasUpdated )
    // do something with selectedItem
  else
    // do whatever you whenever your array is updated
}

Важливо відзначити, що ви могли б знати , який пункт був доданий , якщо ви знаєте , є чи pushабо unshiftвикористовували. Просто перегляньте останній елемент масиву або перший і вуаля.


Я використовую інший підхід: відстежуйте, чи був елемент інструментований в самому елементі. Дивіться мою відповідь вище
Гелін Ло

-2

Спробуйте vm.myArray().arrayChanged.subscribe(function(eventArgs))

Це має додану вартість, коли додається елемент, і вилучену вартість, коли елемент вилучається.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.