什么时候使用 ko.utils.unwrapObservable?

IT技术 javascript knockout.js
2021-03-05 16:20:06

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

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

在这种情况下,他们通过调用 observable()但也调用ko.utils.unwrapObservable. 我只是想弄清楚何时使用一个与另一个,或者我是否应该始终遵循上述模式并同时使用两者。

2个回答

您应该ko.utils.unwrapObservable在不知道是否已获得 observable 的情况下使用这通常是在自定义绑定中,可以将 observable 或 non-observable 绑定到它。

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

@IvanNikitin - 当然,只是想指出它ko.unwrap在 3.0+ 中可用。如果您使用的是 3.0 之前的版本,那么ko.utils.unwrapObservable仍然存在。
2021-04-25 16:20:06
我想我对目的ko.utils.unwrapObservable什么感到困惑查看代码,它只是检查它是否是可观察的,如果是,则 Knockout 调用()以获取可观察的值,否则,它只返回不可观察的值。如果我感兴趣的只是传递到绑定中的数据的值,为什么我不能总是使用()
2021-04-26 16:20:06
你不知道你是否在绑定中传递了一个可观察的或不可观察的。说我有myBinding,有人绑定即喜欢data-bind="myBinding: myValue"myValue可能是一个 observable 或者它可能只是视图模型上的一个普通属性。如果它只是一个属性,而我将其称为函数,那么您将收到错误消息。 ko.utils.unwrapObservable无论您是否通过可观察对象,都会安全地返回您的值。
2021-04-28 16:20:06
这真的取决于情况。一些自定义绑定被设计为只与 observable 一起工作,所以你可以预先检查 (ko.isObservable) 它是一个 observable,然后你可以自由地用 () 解包它。如果您正在接收一个可能具有嵌套 observable 的对象,那么您最好执行 ako.toJS(yourObject)而不是使用ko.utils.unwrapObservable,如果您试图获得对象的解包版本以传递到小部件或第 3 方库。一般来说,最安全的做法是 ko.utils.unwrapObservable用来支持 observables 和 non-observables。
2021-05-02 16:20:06
我还建议使用 'ko.unwrap' 速记,因为 'ko.utils.unwrapObservable' 是一个很长的表达式。
2021-05-08 16:20:06

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

以下递归展开所有内容:

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 总是包含一个值。我不需要担心我是否传入了一个函数、一个 observable、一个值,甚至一个 observable 中的函数。这将正确展开所有内容,直到它到达我想要的对象。

希望能帮助某人。