¿Cuándo usar ko.utils.unwrapObservable?


114

Escribí algunos enlaces personalizados usando KnockoutJS. Todavía no estoy seguro de cuándo usar. ko.utils.unwrapObservable(item)Mirando el código, esa llamada básicamente verifica si itemes un observable. Si es así, devuelve el valor (), si no es así, devuelve el valor. Mirando la sección sobre Knockout sobre la creación de enlaces personalizados, tienen la siguiente sintaxis:

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

En este caso, invocan la vía observable ()pero luego también llaman ko.utils.unwrapObservable. Solo estoy tratando de saber cuándo usar uno frente al otro o si debo seguir siempre el patrón anterior y usar ambos.

Respuestas:


142

Debe usarlo ko.utils.unwrapObservableen los casos en que no sepa si se le ha dado un observable o no. Esto sería comúnmente en un enlace personalizado donde un observable o no observable podría estar vinculado a él.

En el código que tiene arriba, la llamada a valueAccessor()no está realmente desenvolviendo un observable. Solo está recuperando el valor que se pasó al enlace en el contexto correcto (se envuelve en una función para protegerlo). El valor de retorno de valueAccessor()puede ser observable o no. Es lo que se pasó al enlace.


4
Realmente depende de la situación. Algunos enlaces personalizados están diseñados para funcionar solo con observables, por lo que puede verificar por adelantado (ko.isObservable) que es un observable y luego podrá desenvolverlo con (). Si está recibiendo un objeto que puede tener observables anidados, entonces es mejor hacer un en ko.toJS(yourObject)lugar de usar ko.utils.unwrapObservable, si está tratando de obtener una versión sin empaquetar del objeto para pasar a un widget o biblioteca de terceros. En general, es más seguro utilizarlo ko.utils.unwrapObservablepara respaldar observables y no observables.
RP Niemeyer

2
Supongo que estoy confundido con cuál es el propósito ko.utils.unwrapObservable. Al mirar el código, solo verifica si es observable y, si lo es, Knockout invoca ()para obtener el valor de lo observable; de ​​lo contrario, solo devuelve el valor de no observable. Si todo lo que me interesa es el valor de los datos que se pasan al enlace, ¿por qué no puedo usarlo siempre ()?
arb

17
No sabe si está pasando un observable o no observable en un enlace. Digamos que tengo myBindingy alguien se une, es decir, me gusta data-bind="myBinding: myValue". myValuepodría ser un observable o podría ser simplemente una propiedad simple en el modelo de vista. Si es solo una propiedad y la llamo como una función, obtendrá un error. ko.utils.unwrapObservablele devolverá el valor de forma segura independientemente de si se le pasó un observable o no.
RP Niemeyer

10
También recomendaría usar la abreviatura 'ko.unwrap' porque 'ko.utils.unwrapObservable' es una expresión muy larga.
Ivan Nikitin

3
@IvanNikitin: claro, solo quería señalar que ko.unwrapestá disponible en 3.0+. Si está utilizando una versión anterior a 3.0, ko.utils.unwrapObservabletodavía está ahí.
RP Niemeyer

12

La respuesta anterior es correcta, pero a menudo paso funciones a enlaces personalizados (una función que verifica los permisos o determina qué hacer en función de otra cosa, etc.). Lo que realmente necesitaba era desenvolver cualquier función, incluso si no es observable.

Lo siguiente desenvuelve de forma recursiva TODO:

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

Aquí hay un ejemplo de un enlace personalizado simple que escribí:

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

De esta forma, bindingValue siempre contiene un valor. No necesito preocuparme por si pasé una función, un observable, un valor o incluso una función dentro de un observable. Esto desenvolverá correctamente todo hasta que llegue al objeto que quiero.

Espero que ayude a alguien.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.