增强和钩入敲除绑定机制

时间:2014-02-03 08:40:25

标签: performance knockout.js

这是我一直试图做的事情已经有一段时间了。我已经做了一些事情,但我很确定有更好的方法。

问题

我希望能够使用前缀(或类似的东西)挂钩bindingProvider进程来扩充observable的名称

所以,如果我有:

<button data-bind="text: label"></button>

我希望能够拦截绑定的processig并将label替换为myLabel,因此它基本上处理为:

<button data-bind="text: myLabel"></button>

并且基于ViewModel上的一些数据正在应用于节点。

尝试

  1. 使用preprocessNode并在KO到达之前将label值替换为myLabel

    显然,我想避免这样做,特别是因为myLabel只能在某些情况下使用 - 因为它基于ViewModel上的动态数据。

    此外,没有bindingContext引用可用,因此我不确定如何访问ViewModel。

  2. 使用自定义bindingProvider并在$data

  3. 中执行一些字符串/ getBindings混搭
  4. 使用preprocess并增加值

    如果不是两件事,这将是完美的候选人:我将不得不重复所有绑定,因为表单是ko.bindingHandlers.<name>.preprocess它不会给我bindingContext < / strong>,所以我无法使用ViewModel数据:)

  5. 使用扩展程序

    这个问题是我需要将增强行为应用于所有可观察值,而不仅仅是特定值。默认情况下。

  6. 有什么建议吗?

    谢谢。

    示例

    进一步说明要求 - 假设我有一个看起来像这样的模板:

    <ul data-bind="foreach: people">
        <li>
            <span data-bind="text: name"></span>,
            <span data-bind="text: age"></span>
        </li>
    </ul>
    

    微不足道的。现在假设ViewModel数据如下所示:

    {
        people: [
            {name: 'John', age: 30},
            {name: 'Dean', age: 40},
            {age: 0.2}
        ]
    }
    

    基本上,有些人,其中一些人刚刚出生,但还没有名字。 我希望能够为那些无名且未满1岁的人返回类似'noname'的东西。

    我显然可以通过更改模板来实现,但这是我不想做的事情。模板可以重复用于根据性别打印noname的内容,而不是年龄或类似内容。

    希望有所帮助。

2 个答案:

答案 0 :(得分:1)

解决此特定用例的另一种方法是自定义绑定,它将属性名称作为字符串,并使用绑定处理程序的viewModel参数将文本设置为给定属性。

这样的绑定可能如下所示:

ko.bindingHandlers.customText = {
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var field = ko.unwrap(valueAccessor())
        element.innerText = ko.unwrap(viewModel[field]);
    }
}

这是一个完整的jsfiddle示例。

您还可以执行比直接属性名称查找更复杂的操作 - 您甚至可以将函数传递给绑定,该绑定将视图模型作为参数并返回相关数据。

答案 1 :(得分:0)

所以,可观察的是要走的路,谢谢所有建议的人。

最终我的一位同事有一个想法,结果证明这是一个非常漂亮的简单伎俩(而且我正在为此而嘲笑我。)

这个想法是基于为label可观察的mylabel创建label。除了ViewModel 已经具有不相关的myLabel可观察的情况之外,这在大多数情况下都适用,然后将被计算机覆盖 - 这可能是不希望的。

对于ViewModel observable,我想要映射到(在上面的示例中为label),而不是原始的label,而是创建一个名为label的计算器(这样模板)仍然像以前一样工作),但一个技巧是将label可观察的添加到ViewModel 本身,而不是添加到以ViewModel为原型实例化的对象

Tha方式 - 应用此ViewModel的所有其他元素将使用它具有的label值,对于此特定模板,新的var Context = function() { // create computed observable `label` for observable `myLabel` // based on whatever ViewModel data is needed. }; Context.prototype = ViewModel; var context = new Context(); ko.applyBindings(context, node); 计算将影响“旧的“一个 - 这是期望的效果。

基本上:

{{1}}