Wann soll ko.utils.unwrapObservable verwendet werden?


114

Ich habe einige benutzerdefinierte Bindungen mit KnockoutJS geschrieben. Ich bin mir immer noch nicht sicher, wann ich ko.utils.unwrapObservable(item)den Code verwenden soll. Bei diesem Aufruf wird im Grunde geprüft, ob itemer beobachtbar ist. Wenn dies der Fall ist, geben Sie den Wert () zurück. Wenn dies nicht der Fall ist, geben Sie einfach den Wert zurück. Im Abschnitt über Knockout zum Erstellen benutzerdefinierter Bindungen haben sie die folgende Syntax:

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

In diesem Fall rufen sie das Observable via auf (), rufen dann aber auch auf ko.utils.unwrapObservable. Ich versuche nur herauszufinden, wann ich eines gegen das andere verwenden soll oder ob ich einfach immer dem obigen Muster folgen und beide verwenden soll.

Antworten:


142

Sie sollten ko.utils.unwrapObservablein Fällen verwenden, in denen Sie nicht wissen, ob Sie eine beobachtbare erhalten haben oder nicht. Dies würde üblicherweise in einer benutzerdefinierten Bindung erfolgen, bei der eine beobachtbare oder nicht beobachtbare Bindung daran gebunden sein könnte.

In dem Code, den Sie oben haben, wird beim Aufruf von valueAccessor()nicht ein Observable ausgepackt. Es wird nur der Wert abgerufen, der im richtigen Kontext an die Bindung übergeben wurde (sie wird in eine Funktion eingeschlossen, um sie zu schützen). Der Rückgabewert von valueAccessor()kann beobachtbar sein oder nicht. Es ist alles, was an die Bindung übergeben wurde.


4
Es kommt wirklich auf die Situation an. Einige benutzerdefinierte Bindungen funktionieren nur mit Observablen. Sie können daher im Voraus überprüfen (ko.isObservable), ob es sich um eine Observable handelt, und sie dann mit () auspacken. Wenn Sie ein Objekt erhalten, das möglicherweise verschachtelte Observablen enthält, ist es besser, eine zu ko.toJS(yourObject)verwenden ko.utils.unwrapObservable, als sie zu verwenden , wenn Sie versuchen, eine entpackte Version des Objekts in ein Widget oder eine Bibliothek eines Drittanbieters zu übertragen. Im Allgemeinen ist die Verwendung ko.utils.unwrapObservablezur Unterstützung von Observablen und Nicht-Observablen am sichersten .
RP Niemeyer

2
Ich glaube, ich bin verwirrt mit dem Zweck ko.utils.unwrapObservable. Wenn Sie sich den Code ansehen, wird nur geprüft, ob er beobachtbar ist. Wenn dies ()der Fall ist, ruft Knockout auf , um den Wert des beobachtbaren Codes abzurufen. Andernfalls wird nur der Wert für nicht beobachtbar zurückgegeben. Wenn mich nur der Wert der an die Bindung übergebenen Daten interessiert, warum kann ich ihn dann nicht immer verwenden ()?
Arb

17
Sie wissen nicht, ob Sie in einer Bindung ein Observable oder ein Non-Observable erhalten. Sagen wir, ich habe myBindingund jemand bindet dh wie data-bind="myBinding: myValue". myValueMöglicherweise handelt es sich um eine beobachtbare Eigenschaft oder nur um eine einfache Eigenschaft des Ansichtsmodells. Wenn es nur eine Eigenschaft ist und ich sie wie eine Funktion aufrufe, erhalten Sie eine Fehlermeldung. ko.utils.unwrapObservablewird Ihnen den Wert sicher zurückgeben, unabhängig davon, ob Sie ein Observable bestanden haben oder nicht.
RP Niemeyer

10
Ich würde auch empfehlen, die Kurzform 'ko.unwrap' zu verwenden, da 'ko.utils.unwrapObservable' ein sehr langer Ausdruck ist.
Ivan Nikitin

3
@IvanNikitin - sicher, wollte nur darauf hinweisen, dass ko.unwrapes in 3.0+ verfügbar ist. Wenn Sie älter als 3.0 verwenden, ko.utils.unwrapObservableist es immer noch da.
RP Niemeyer

12

Die frühere Antwort ist richtig, aber oft übergebe ich Funktionen an benutzerdefinierte Bindungen (eine Funktion, die Berechtigungen überprüft oder basierend auf etwas anderem usw. bestimmt, was zu tun ist). Was ich wirklich brauchte, war, jede Funktion auszupacken, auch wenn sie nicht beobachtbar ist.

Folgendes packt rekursiv ALLES aus:

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

Hier ist ein Beispiel für eine einfache benutzerdefinierte Bindung, die ich geschrieben habe:

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

Auf diese Weise enthält bindingValue immer einen Wert. Ich muss mir keine Sorgen machen, ob ich eine Funktion, ein Observable, einen Wert oder sogar eine Funktion innerhalb eines Observable übergeben habe. Dadurch wird alles ordnungsgemäß ausgepackt, bis das gewünschte Objekt erreicht ist.

Hoffe das hilft jemandem.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.