Когда использовать ko.utils.unwrapObservable?

114

Я написал несколько пользовательских привязок с помощью KnockoutJS. Я все еще не уверен, когда использовать. ko.utils.unwrapObservable(item)Глядя на код, этот вызов в основном проверяет, itemявляется ли наблюдаемым. Если это так, верните значение (), если нет, просто верните значение. Если посмотреть на раздел Knockout о создании пользовательских привязок, у них следующий синтаксис:

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

В этом случае они вызывают наблюдаемое переходное отверстие, ()но затем также вызывают ko.utils.unwrapObservable. Я просто пытаюсь понять, когда использовать одно по сравнению с другим, или я должен всегда следовать приведенному выше шаблону и использовать оба.

АРБ
источник

Ответы:

142

Вам следует использовать ko.utils.unwrapObservableв случаях, когда вы не знаете, было ли вам дано наблюдаемое или нет. Обычно это происходит в пользовательской привязке, где наблюдаемое или ненаблюдаемое может быть связано с ним.

В приведенном выше коде вызов valueAccessor()фактически не разворачивает наблюдаемый объект. Он просто извлекает значение, которое было передано привязке в правильном контексте (оно оборачивается функцией для его защиты). Возвращаемое значение valueAccessor()может быть наблюдаемым или нет. Это то, что было передано в привязку.

Р.П. Нимейер
источник
4
Это действительно зависит от ситуации. Некоторые пользовательские привязки предназначены для работы только с наблюдаемыми объектами, поэтому вы можете заранее (ko.isObservable) проверить, что это наблюдаемый объект, а затем вы сможете развернуть его с помощью (). Если вы получаете объект, который может иметь вложенные наблюдаемые объекты, то вам лучше сделать это ko.toJS(yourObject), чем использовать ko.utils.unwrapObservable, если вы пытаетесь получить развернутую версию объекта для передачи в виджет или стороннюю библиотеку. В общем, безопаснее всего использовать ko.utils.unwrapObservableдля поддержки наблюдаемых и ненаблюдаемых.
RP Niemeyer
2
Думаю, меня смущает цель ko.utils.unwrapObservable. Глядя на код, он просто проверяет, является ли он наблюдаемым, и если это так, Knockout вызывает, ()чтобы получить значение наблюдаемого, в противном случае он просто возвращает значение для ненаблюдаемого. Если меня интересует только значение данных, переданных в привязку, почему я не могу просто всегда использовать ()?
arb
17
Вы не знаете, передаете ли вы наблюдаемый или ненаблюдаемый в привязке. Скажем , у меня есть myBindingи кто - то связывает , т.е. как data-bind="myBinding: myValue". myValueможет быть наблюдаемым или простым свойством в модели представления. Если это просто свойство, и я называю его функцией, вы получите сообщение об ошибке. ko.utils.unwrapObservableбезопасно вернет вам значение независимо от того, было ли вам передано наблюдаемое или нет.
RP Niemeyer
10
Я также рекомендовал бы использовать сокращение ko.unwrap, потому что ko.utils.unwrapObservable - это очень длинные выражения.
Иван Никитин
3
@IvanNikitin - конечно, просто хотел отметить, что ko.unwrapдоступно в версии 3.0+ . Если вы используете более раннюю версию, чем 3.0, то ko.utils.unwrapObservableвсе еще есть.
RP Niemeyer
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 всегда содержит значение. Мне не нужно беспокоиться о том, передал ли я функцию, наблюдаемый объект, значение или даже функцию внутри наблюдаемого. Это будет правильно разворачивать все, пока не доберется до нужного мне объекта.

Надеюсь, это кому-то поможет.

Pilavdzice
источник