Расширение наблюдаемого в пользовательской привязке - PullRequest
0 голосов
/ 05 ноября 2018

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

Обработчик привязки работает правильно, и функция update вызывается при обновлении любого из свойств наблюдаемой. Однако функция update вызывается для каждого обновленного свойства, что приводит к странному поведению, поскольку я полагаюсь на весь объект, который будет доступен и обновлен.

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

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

Я пробовал много разных методов, включая:

Все, что не сработало.

Я не нашел другого обработчика привязки, который бы отдаленно приближался к такого рода функциям и пытался соединить его вместе с другими функциями.

Сам мой код привязки относительно прост: я беру связанный объект и просто разделяю параметры и передаю их экземпляру Code Mirror.

ko.bindingHandlers.editor = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        var observableValue = ko.utils.unwrap(valueAccessor());
        initEditor(element, observableValue, allBindingsAccessor);
    },
    update: function(element, valueAccessor, allBindingsAccessor) {
        var observableValue = ko.unwrap(valueAccessor());

        createEditor(codeEditorDiv, observableValue);
        resize();
        updateEditor(element, observableValue, allBindingsAccessor);
    }
};

И мой HTML-код:

 <div id="editor" data-bind="editor: EditorVM"></div>

Я использую Dotnetify для ViewModel, так что это разумный сложный класс C #, но достаточно сказать, что привязка работает и обновляется, но мне нужно, чтобы он вызывал «update» только один раз свойства были обновлены.

1 Ответ

0 голосов
/ 05 ноября 2018

К сожалению, вы не показали, что initEditor, createEditor и updateEditor делают с observableValue, потому что это, вероятно, то место, где вы должны расширять свои наблюдаемые.

Методы привязки init и update создают вычисляемые зависимости, это означает, что любая наблюдаемая , развернутая в стеке вызовов, начиная с init, вызовет метод update называется.

В абстрактном примере:

const someVM = ko.observable({
  a: ko.observable(1),
  b: ko.observable(2),
  c: ko.observable(3)
});

// Some function that unwraps properties
const logABC = function(vm) {
  console.log(
    vm.a(),
    vm.b(),
    vm.c()
  );
}

// Regular binding update:
ko.computed(function update() {
  console.log(
    "Regular binding update:",
  )
  logABC(someVM())
});

// Change VM
someVM(someVM());

// Change a, b, and c
someVM().a("A");
someVM().b("B");
someVM().c("C");
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

Обратите внимание, что update называется:

  1. При инициализации вычисляется
  2. При изменении наблюдаемой, содержащей модель представления
  3. При изменении любых наблюдаемых свойств модели представления

Есть несколько способов решения проблемы, из которых самый простой - создать свой собственный computed в методе привязки init и расширить его до deferred.

const someVM = ko.observable({
  a: ko.observable(1),
  b: ko.observable(2),
  c: ko.observable(3)
});

const getABC = function(vm) {
  return [vm.a(), vm.b(), vm.c()].join(", ");
}

ko.bindingHandlers.renderABC = {
  init: function(el, va) {
    el.innerText += "Init.\n";
    
    // This ensures any inner unwrapping gets deferred
    var updateSub = ko.computed(function update() {
      el.innerText += getABC(ko.unwrap(va())) + "\n";
    }).extend({ deferred: true });
    
    ko.utils.domNodeDisposal.addDisposeCallback(el, function() {
      updateSub.dispose();
    });
  }
}

ko.applyBindings({ someVM: someVM });

// Change VM
someVM(someVM());

// Change a, b, and c
someVM().a("A");
someVM().b("B");
someVM().c("C");


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...