何时使用ko.utils.unwrapObservable?

arb*_*arb 112 javascript knockout.js

我使用KnockoutJS编写了一些自定义绑定.我仍然不确定何时使用ko.utils.unwrapObservable(item)查看代码,该调用基本上检查是否item是可观察的.如果是,则返回值(),如果不是,则返回值.查看Knockout关于创建自定义绑定的部分,它们具有以下语法:

var value = valueAccessor(), allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,他们调用observable via (),然后调用ko.utils.unwrapObservable.我只是试图了解何时使用一个与另一个或如果我应该始终遵循上述模式并使用两者.

RP *_*yer 140

ko.utils.unwrapObservable如果您不知道您是否获得了可观察量,您应该使用.这通常是在自定义绑定中,可观察或不可观察的绑定可以绑定它.

在上面的代码中,调用valueAccessor()实际上并没有展开observable.它只是检索在正确的上下文中传递给绑定的值(它被包装在一个函数中以保护它).返回值valueAccessor()可以是可观察的或不可观察的.它是传递给绑定的任何东西.

  • 您不知道您是否在绑定中传递了可观察或不可观察的内容.假设我有'myBinding`并且有人绑定,比如`data-bind ="myBinding:myValue"`.`myValue`可能是一个可观察的,也可能只是视图模型上的一个普通属性.如果它只是一个属性而我将其称为函数,那么您将收到错误.无论你是否传递了一个observable,`ko.utils.unwrapObservable`都会安全地返回值. (17认同)
  • 我还建议使用'ko.unwrap'速记,因为'ko.utils.unwrapObservable'是一个非常长的表达式. (10认同)
  • 这取决于具体情况.一些自定义绑定被设计为仅与observable一起使用,因此您可以检查前面(ko.isObservable)它是否是可观察的,然后您可以自由地用()展开它.如果你正在接收一个可能有嵌套observable的对象,那么你最好不要使用`ko.toJS(yourObject)`而不是使用`ko.utils.unwrapObservable`,如果你试图得到一个未包装的对象版本传递到小部件或第三方库.通常,使用`ko.utils.unwrapObservable`来支持observable和non-observable是最安全的. (4认同)
  • @IvanNikitin - 当然,只是想指出`ko.unwrap`在3.0+中可用.如果你使用的是3.0以上,那么`ko.utils.unwrapObservable`仍然存在. (3认同)
  • 我想我对`ko.utils.unwrapObservable`的目的感到困惑.查看代码,它只是检查它是否是可观察的,如果是,Knockout调用`()`来获取observable的值,否则,它只返回non-observable的值.如果我感兴趣的是传递给绑定的数据的值,为什么我不能只使用`()`? (2认同)

pil*_*ice 11

较早的答案是正确的,但我经常将函数传递给自定义绑定(一种检查权限的函数,或根据其他内容确定要执行的操作等).我真正需要的是解开任何功能,即使它不是一个可观察的功能.

以下递归地解开一切:

ko.utils.unwrapFunction = function (func) {
    if (typeof func != 'function') {
        return func;
    }
    else {
        return ko.utils.unwrapFunction(func());
    }
};
Run Code Online (Sandbox Code Playgroud)

这是我写的一个简单自定义绑定的示例:

//replaces single and double 'smart' quotes users commonly paste in from word into textareas and textboxes with normal text equivalents
//USAGE:
//data-bind="replaceWordChars:true
//also works with valueUpdate:'keyup' if you want"

ko.bindingHandlers.replaceWordChars = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var bindingValue = ko.utils.unwrapFunction(valueAccessor);

        if (bindingValue) {
            $(element).val(removeMSWordChars(allBindingsAccessor().value())); //update DOM - not sure why I should need to do this, but just updating viewModel doesn't always update DOM correctly for me
            allBindingsAccessor().value($(element).val()); //update viewModel
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,bindingValue总是包含一个值.如果我在一个observable中传入一个函数,一个observable,一个值或一个函数,我不需要担心.这将正确解开所有内容,直到它到达我想要的对象.

希望能帮助别人.