Kiedy używać ko.utils.unwrapObservable?


114

Napisałem kilka niestandardowych powiązań za pomocą KnockoutJS. Nadal nie jestem pewien, kiedy użyć ko.utils.unwrapObservable(item)Patrząc na kod, to wywołanie zasadniczo sprawdza, czy itemjest obserwowalne. Jeśli tak, zwróć wartość (), jeśli nie, po prostu zwróć wartość. Patrząc na sekcję Knockout dotyczącą tworzenia niestandardowych powiązań, mają one następującą składnię:

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

W tym przypadku wywołują obserwowalne via, ()ale potem również wywołują ko.utils.unwrapObservable. Po prostu staram się ustalić, kiedy użyć jednego z drugim, czy też powinienem zawsze postępować zgodnie z powyższym wzorem i używać obu.

Odpowiedzi:


142

Powinieneś używać ko.utils.unwrapObservablew przypadkach, gdy nie wiesz, czy otrzymałeś obserwowalne, czy nie. Zwykle miałoby to miejsce w niestandardowym powiązaniu, w którym można by powiązać to, co można zaobserwować lub nie.

W kodzie, który masz powyżej, wywołanie valueAccessor()nie jest w rzeczywistości rozpakowywaniem obserwowalnego. Po prostu pobiera wartość, która została przekazana do powiązania w odpowiednim kontekście (zostaje opakowana w funkcję, aby ją chronić). Wartość zwracana valueAccessor()może być obserwowalna lub nie. To wszystko, co zostało przekazane do oprawy.


4
To naprawdę zależy od sytuacji. Niektóre niestandardowe powiązania są zaprojektowane tak, aby działały tylko z obserwa- bami, więc możesz sprawdzić z góry (ko.isObservable), czy jest to obserwowalne, a następnie możesz je rozpakować za pomocą (). Jeśli otrzymujesz obiekt, który może mieć zagnieżdżone obserwowalne, lepiej zrobić, ko.toJS(yourObject)a nie używać ko.utils.unwrapObservable, jeśli próbujesz uzyskać nieopakowaną wersję obiektu, aby przejść do widgetu lub biblioteki innej firmy. Ogólnie rzecz biorąc, najbezpieczniej jest używać go ko.utils.unwrapObservabledo obsługi obserwabli i nieobserwowalnych.
RP Niemeyer

2
Myślę, że jestem zdezorientowany, jaki jest cel ko.utils.unwrapObservable. Patrząc na kod, po prostu sprawdza, czy jest obserwowalny, a jeśli tak jest, Knockout wywołuje ()wartość tego, co jest obserwowalne, w przeciwnym razie zwraca tylko wartość dla nieobserwowalnego. Jeśli interesuje mnie tylko wartość danych przekazanych do powiązania, dlaczego nie mogę po prostu zawsze używać ()?
arb

17
Nie wiesz, czy otrzymujesz obserwowalne, czy nieobserwowalne w powiązaniu. Powiedz, że mam myBindingi ktoś wiąże tj data-bind="myBinding: myValue". Jak . myValuemoże być obserwowalna lub może to być zwykła właściwość w modelu widoku. Jeśli jest to tylko właściwość i nazywam to funkcją, wtedy pojawi się błąd. ko.utils.unwrapObservablebezpiecznie zwróci Ci wartość niezależnie od tego, czy otrzymałeś obserwowalny, czy nie.
RP Niemeyer

10
Poleciłbym również używanie skrótu „ko.unwrap”, ponieważ „ko.utils.unwrapObservable” to bardzo długie wyrażenia.
Ivan Nikitin

3
@IvanNikitin - oczywiście, chciałem tylko zaznaczyć, że ko.unwrapjest dostępny w wersji 3.0+. Jeśli używasz starszego niż 3.0, ko.utils.unwrapObservableto nadal tam jest.
RP Niemeyer

12

Wcześniejsza odpowiedź jest poprawna, ale często przekazuję funkcje do niestandardowych powiązań (funkcja, która sprawdza uprawnienia lub określa, co zrobić na podstawie czegoś innego itp.). To, czego naprawdę potrzebowałem, to rozpakowanie dowolnej funkcji, nawet jeśli nie jest ona obserwowalna.

Następujący rekurencyjnie rozpakowuje WSZYSTKO:

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

Oto przykład prostego niestandardowego wiązania, które napisałem:

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

W ten sposób bindingValue zawsze zawiera wartość. Nie muszę się martwić, czy przekazałem funkcję, obserwowalną, wartość czy nawet funkcję wewnątrz obserowalnej. Spowoduje to prawidłowe rozpakowanie wszystkiego, aż dotrze do obiektu, który chcę.

Mam nadzieję, że to komuś pomoże.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.