116 votes

Quand utiliser ko.utils.unwrapObservable?

J'ai écrit quelques liaisons personnalisées en utilisant KnockoutJS. Je ne suis toujours pas certain quand utiliser ko.utils.unwrapObservable(item). En regardant le code, cet appel vérifie essentiellement si item est un observable. Si c'est le cas, retourner la valeur(), sinon, simplement retourner la valeur. En examinant la section sur Knockout concernant la création de liaisons personnalisées, ils ont la syntaxe suivante :

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

Dans ce cas, ils invoquent l'observable via () mais appellent également ko.utils.unwrapObservable. J'essaie juste de comprendre quand utiliser l'un ou l'autre ou si je devrais simplement toujours suivre le modèle ci-dessus et utiliser les deux.

147voto

RP Niemeyer Points 81663

Vous devez utiliser ko.utils.unwrapObservable dans les cas où vous ne savez pas si vous avez reçu un observable ou non. Cela se produit généralement dans une liaison personnalisée où un observable ou non observable pourrait y être lié.

Dans le code que vous avez ci-dessus, l'appel à valueAccessor() n'est pas vraiment en train de déballer un observable. Il récupère simplement la valeur qui a été passée à la liaison dans le bon contexte (elle est enveloppée dans une fonction pour la protéger). La valeur de retour de valueAccessor() peut être un observable ou non. C'est ce qui a été passé à la liaison.

0 votes

Est-ce que le modèle que j'ai publié est la meilleure pratique pour les liaisons personnalisées à l'avenir?

6 votes

Il dépend vraiment de la situation. Certains bindings personnalisés sont conçus pour fonctionner uniquement avec des observables, donc vous pouvez vérifier à l'avance (ko.isObservable) s'il s'agit d'un observable, puis vous seriez libre de le déballer avec (). Si vous recevez un objet qui peut contenir des observables imbriqués, il est préférable d'utiliser ko.toJS(votreObjet) plutôt que d'utiliser ko.utils.unwrapObservable, si vous essayez d'obtenir une version déballée de l'objet à passer à un widget ou une bibliothèque tierce. En général, il est plus sûr d'utiliser ko.utils.unwrapObservable pour prendre en charge les observables et les non-observables.

2 votes

Je suppose que je suis confus quant au but de ko.utils.unwrapObservable. En regardant le code, il vérifie simplement s'il est observable et, le cas échéant, Knockout invoque () pour obtenir la valeur de l'observable, sinon, il renvoie simplement la valeur pour un non-observable. Si tout ce qui m'intéresse est la valeur des données transmises à la liaison, pourquoi ne puis-je pas utiliser () tout le temps ?

14voto

pilavdzice Points 349

La réponse précédente est correcte, mais souvent je transmets des fonctions à des liaisons personnalisées (une fonction qui vérifie les autorisations, ou détermine quoi faire en fonction de quelque chose d'autre, etc). Ce dont j'avais vraiment besoin était de déballer toute fonction, même si ce n'est pas un observable.

Le code suivant déballe RÉCURREMMENT TOUT :

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

Voici un exemple d'une simple liaison personnalisée que j'ai écrite :

// remplace les guillemets simples et doubles 'intelligents' que les utilisateurs collent souvent depuis Word dans les zones de texte et les zones de texte par des équivalents de texte normal
// USAGE :
// data-bind="replaceWordChars:true
// fonctionne également avec valueUpdate:'keyup' si vous le souhaitez"

ko.bindingHandlers.replaceWordChars = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var bindingValue = ko.utils.unwrapFunction(valueAccessor);

        if (bindingValue) {
            $(element).val(removeMSWordChars(allBindingsAccessor().value())); // mettre à jour le DOM - je ne suis pas sûr pourquoi j'aurais besoin de le faire, mais mettre à jour simplement le viewModel ne met pas toujours correctement à jour le DOM pour moi
            allBindingsAccessor().value($(element).val()); // mettre à jour le viewModel
        }
    }
}

De cette manière, bindingValue contient toujours une valeur. Je n'ai pas besoin de m'inquiéter si j'ai transmis une fonction, un observable, une valeur, ou même une fonction à l'intérieur d'un observable. Cela déballera correctement tout jusqu'à ce qu'il atteigne l'objet voulu.

J'espère que cela aidera quelqu'un.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X