【问题标题】:Changing order that Knockout bindings are applied更改应用 Knockout 绑定的顺序
【发布时间】:2012-12-11 03:28:28
【问题描述】:

我正在创建一个 Knockout 绑定,它将作为 jQuery 小部件的包装器工作。此小部件将事件处理程序应用于子元素。不幸的是,小部件的事件处理直接应用于子元素,而不是委托。问题是我在同一个元素上有一个foreach 绑定,但我需要在应用foreach 绑定之后应用自定义绑定

显然,正确的做法是修复 jQuery 插件,但目前这不是一个选项。我想知道是否有任何适合我的解决方法。例如,有没有办法执行以下任何操作?

  1. 检测是否已应用特定绑定
  2. 影响绑定应用的顺序
  3. 安全地强制执行另一个绑定

更新:

我应该提到的一个方面是这个自定义和foreach 绑定驻留在模板中。因此,直接修改 DOM 的解决方案对我不起作用,因为它实际上会修改模板。

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    在你的 bindingHandler 上添加一个 after 属性和一个依赖数组

    ko.bindingHandlers.myHandler = {
        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            // Actual code
        },
        update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            // Actual code
        },
        after:['foreach']
    };
    

    【讨论】:

    • 这似乎不起作用 - 你有一些文档的链接或显示它的小提琴吗?
    • 有趣 - 谢谢。果然在淘汰码中。不知道为什么当我尝试它时它不起作用。
    【解决方案2】:

    如果您的绑定依赖于 foreach 绑定,为什么不从您的自定义绑定中调用它呢?然后你甚至不需要在 data-bind 属性中提供它。前几天我帮助了另一个 SO 用户,检查我如何从自定义绑定中调用选项绑定

    http://jsfiddle.net/w9bsc/42/

    ko.applyBindingsToNode(element, { options: valueAccessor(), optionsCaption: caption, optionsText: optionsText  }, viewModel);
    

    【讨论】:

    • 感谢您的回答。我实际上尝试了你所做的(使用applyBindingsToNode),它似乎有效。我之前没有提到的一个复杂情况是我的自定义绑定应用于text/html 模板。在使用foreach 执行applyBindingsToNode 之后,创建了子节点,但它们被永久插入到模板的 DOM 中,而不是模板实例的 DOM 中,如果你明白我的意思的话。
    • 您应该使用模板绑定而不是 foreach,但也许这就是您所做的?
    • 我都试过了。不管怎样,applyBindingsToNode 改变了模板内部的 DOM。
    • 那你做错了,模板绑定应该只使用script标签来获取模板,它应该呈现在声明模板绑定的标签中
    • 会,但如果您直接致电applyBindingsToNode,则不会。
    【解决方案3】:

    我找到了一种解决方法,但它比我喜欢的更像是一种 hack。我仍然会等待更好的答案。

    我所做的只是这样:

    ko.bindingHandlers.myHandler = {
        init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            if (allBindingsAccessor().foreach) {
                setTimeout(doInit, 1);
            } else {
                doInit();
            }
    
            function doInit() {
                bindingContext.initializedMyHandler = true;
                // Actual code
            }
        },
        update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            if (bindingContext.initializedMyHandler) {
                doUpdate();
            } else {
                setTimeout(doUpdate, 1);
            }
            function doUpdate() {
                // Actual code
            }
        }
    };
    

    基本上我只是使用超时来推迟执行。这样,其余的绑定处理程序将首先执行。

    【讨论】:

      猜你喜欢
      • 2021-12-08
      • 2014-05-05
      • 2017-04-25
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 2019-04-15
      • 2016-04-16
      • 2015-11-06
      相关资源
      最近更新 更多