Простой и понятный способ синхронизации наблюдаемых из разных моделей представлений.

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

function site1Model(username) {
    this.username = ko.observable(username);
    ....
}

function site2Model(username) = {
    this.username = ko.observable(username);
    ....
}

Эти модели представления независимы и не обязательно связаны друг с другом, но в некоторых случаях третья модель представления создает связь между ними.

function site3Model(username) = {
    this.site1 = new site1Model(username);
    this.site2 = new site2Model(username);
    // we now need to ensure that the usernames are kept the same between site1/2
    ...
}

Вот несколько вариантов, которые я придумал.

  1. Используйте вычисляемую наблюдаемую, которая читает одну и записывает в обе:

    site3Model.username = ko.computed({
    читать: функция () {
    вернуть this.site1.username(); // предполагаем, что они всегда одинаковы
     },
    написать: функция (значение) {
    this.site1.имя пользователя (значение);
    этот.сайт2.имя пользователя (значение);
     },
    владелец: site3Model
    }
    

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

  2. Используйте метод subscribeдля обновления друг друга:

    site3Model.site1.username.subscribe(function(value) {
    this.site2.имя пользователя (значение);
    }, site3Model);
    site3Model.site2.username.subscribe (функция (значение) {
    this.site1.имя пользователя (значение);
    }, site3Model);
    

    Это работает до тех пор, пока наблюдаемые объекты подавляют уведомления, когда значения совпадают; в противном случае вы получите бесконечный цикл. Вы также можете выполнить проверку раньше: if (this.site1.username() !== value) this.site1.username(value);Здесь также есть проблема, заключающаяся в том, что наблюдаемые должны быть простыми ( это не сработает, если site1и site2сами являются наблюдаемыми).

  3. Используйте Computedдля подписки и обновлений:

    site3Model.username1Updater = ko.computed(function() {
    this.site1.username(this.site2.username());
    }, site3Model);
    site3Model.username2Updater = ko.computed (функция () {
    this.site2.имя_пользователя(this.site1.username());
    }, site3Model);
    

    Этот формат позволяет нам иметь другие зависимости. Например, мы можем создать наблюдаемые site1и site2, а затем использовать this.site1().username(this.site2().username());Этот метод также требует проверки на равенство, чтобы избежать бесконечного цикла.Если мы не можем зависеть от наблюдаемого, чтобы сделать это, мы могли бы проверить внутри вычисляемого, но добавили бы другую зависимость от наблюдаемого, который мы обновляем (пока не будет доступно что-то вродеobservable.peek ). У этого метода также есть недостаток, заключающийся в том, что код обновления сначала запускается один раз для установки зависимостей (поскольку именно так работает вычисленный).

Поскольку я считаю, что у всех этих методов есть обратная сторона, есть ли другой способ сделать это, который был бы простым (менее 10 строк кода), эффективным (не запускать ненужный код или обновления) и гибким (обрабатывать несколько уровни наблюдаемых)?

5
задан Michael Best 30 May 2012 в 09:42
поделиться