代码之家  ›  专栏  ›  技术社区  ›  Steve

在自定义绑定中扩展可观察对象

  •  4
  • Steve  · 技术社区  · 7 年前

    我有一个自定义绑定处理程序,我正在绑定到视图模型中的复杂对象。

    update 函数在可观察对象的任何属性更新时调用。然而 更新 每一个

    我理解为什么会发生这种情况,因为每个属性都会导致调用更新,我想我知道如何防止这种情况-使用 deferred updates

    但是,我找不到如何在我的自定义绑定中仅为可观察对象启用延迟更新。我不想在应用程序范围内启用它,因为我正在将绑定编写为库函数。

    我尝试了很多不同的方法,包括:

    所有这些都不起作用。

    我还没有发现任何其他自定义绑定处理程序可以远程接近这类函数,并且一直在尝试将它与其他函数组合在一起。

    我的绑定代码本身相对简单,我使用绑定对象并简单地拆分参数并将其传递给代码镜像实例。

    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

    1 回复  |  直到 7 年前
        1
  •  2
  •   user3297291    7 年前

    不幸的是你没有展示什么 initEditor createEditor updateEditor 用这个做什么 observableValue ,因为这可能是你应该扩展你的观测值的地方。

    这个 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>

    请注意 称为:

    1. 初始化计算机时
    2. 更改包含viewmodel的可观察对象时
    3. 更改时 任何

    有几种方法可以解决这个问题,其中最简单的就是创建自己的 computed 初始化 方法并将其扩展为 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");
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    
    <pre data-bind="renderABC: someVM"></pre>
    推荐文章