何时使用ko.utils.unwrapObservable?


114

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

var value = valueAccessor(), allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);

在这种情况下,它们通过调用observable,()然后又调用ko.utils.unwrapObservable。我只是试图掌握何时使用一个与另一个的关系,或者是否应该始终遵循上述模式并同时使用两者。

Answers:


142

您应该ko.utils.unwrapObservable在不知道是否可以观察到的情况下使用。这通常是在自定义绑定中,其中可观察对象或不可观察对象可以与之绑定。

在上面的代码中,对的调用valueAccessor()实际上并未展开可观察对象。它只是在正确的上下文中检索传递给绑定的值(它包装在函数中以对其进行保护)。的返回值是否valueAccessor()可以观察到。它是传递给绑定的任何内容。


4
这真的取决于情况。某些自定义绑定仅设计用于可观察对象,因此您可以预先检查(ko.isObservable)它是可观察对象,然后可以使用()对其进行自由包装。如果您收到的对象可能具有嵌套的可观察对象,那么最好尝试ko.toJS(yourObject)使用a 而不是使用ko.utils.unwrapObservable,如果您尝试获取该对象的未包装版本以传递到小部件或第3方库中。通常,使用最安全的方法 ko.utils.unwrapObservable来支持可观察和不可观察的对象。
RP Niemeyer 2012年

2
我想我对它的目的感到困惑ko.utils.unwrapObservable。查看代码,它只是检查看是否可观察,如果是,则Knockout调用()以获取可观察的值,否则,它仅返回非可观察的值。如果我只想知道传递给绑定的数据的值,为什么我不能总是使用它()呢?
2012年

17
您不知道绑定中是否传递了可观察的或不可观察的。说我有myBinding,有人约束,例如data-bind="myBinding: myValue"myValue可能是可观察的,也可能只是视图模型上的普通属性。如果它只是一个属性,而我像一个函数一样调用它,那么您将得到一个错误。 ko.utils.unwrapObservable无论您是否通过了观察,都将安全地返回值。
RP Niemeyer 2012年

10
我还建议使用'ko.unwrap'速记,因为'ko.utils.unwrapObservable'是一个很长的表达式。
伊万·尼基丁

3
@IvanNikitin-当然,只是想指出ko.unwrap在3.0+中可用。如果您使用的版本低于3.0,则ko.utils.unwrapObservable仍然存在。
RP Niemeyer 2014年

12

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

以下递归解包一切:

ko.utils.unwrapFunction = function (func) {
    if (typeof func != 'function') {
        return func;
    }
    else {
        return ko.utils.unwrapFunction(func());
    }
};

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

//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
        }
    }
}

这样bindingValue总是包含一个值。我不必担心是否在可观察对象内部传递了一个函数,一个可观察对象,一个值甚至一个函数。这将正确展开所有内容,直到到达我想要的对象为止。

希望能对某人有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.