56 votes

Quelle est la meilleure façon de stocker l'état entre l'init et la mise à jour pour une liaison personnalisée knockout ?

Actuellement, je stocke l'état en utilisant les données jQuery pour l'élément dom.

ko.bindingHandlers.customValue = {

    init: function init(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var state = { isEditing: false };        
        $(element).focus(function focus() {
            state.isEditing = true;
        }).blur(function blur() {
            state.isEditing = false;            
        }).data("customBinding", state);

    },

    update: function update(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        // ignore if updating
        if (!$(element).data("customBinding").isEditing) {
            // handle update if they are not updating                                
        }
    }

};​

Existe-t-il un meilleur endroit pour stocker l'état par liaison qui ne nécessite pas le dom ? Le bindingContext peut-il être utilisé pour stocker l'état pour chaque instance de la liaison ?

47voto

RP Niemeyer Points 81663

El bindingContext est une possibilité, mais seulement pour passer des données de init a update la première fois que la liaison est déclenchée. La fois suivante où update les feux ne seraient plus là.

Il y a vraiment deux choix pour le stockage de ce type d'état :

1- Sur l'élément, comme vous l'avez dit. Vous pouvez utiliser la fonction jQuery $.data ou KO inclut des API pour ce faire également ko.utils.domData.get(element, key) y ko.utils.domData.set(element, key, value) .

2- Mettez ce type d'information dans votre modèle de vue, si nécessaire. Un drapeau pour indiquer isEditing n'est pas nécessairement déplacée dans un modèle de vue. Personnellement, j'aime placer ce type de "méta-données" en tant que sous-observables d'une observable, par exemple :

var name = ko.observable("Bob");
name.isEditing = ko.observable(false);

Vous seriez en mesure de vous lier contre name y name.isEditing .

Cela présente certains avantages :

  • permet de garder le modèle de vue assez propre, car vous n'introduisez pas de nouvelles propriétés de haut niveau.
  • permet de garder la sous-observable liée à son observable parent (pas besoin de nameIsEditing etc.)
  • lorsqu'il est transformé en JSON avec quelque chose comme ko.toJSON le site isEditing sera simplement abandonné lorsque son parent sera déballé. Ainsi, vous n'aurez pas à renvoyer des valeurs inutiles au serveur.
  • dans ce cas, elle peut aussi avoir l'avantage d'être disponible pour d'autres calculs dans votre modèle de vue ou pour être liée à plusieurs éléments dans votre interface utilisateur.

8voto

Michael Best Points 9033

Attacher des données à l'élément est bien, et Knockout utilise cette méthode en interne pour les liaisons de flux de contrôle (if, with, etc.), par exemple.

Une autre méthode consiste à n'utiliser que le init et utiliser un observable calculé pour gérer les mises à jour. J'utilise cette méthode dans mon répéter contraignant. Voici les parties importantes :

ko.bindingHandlers['repeat'] = {
    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        ...
        // set up persistent data
        var lastRepeatCount = 0;
        ...
        ko.computed(function() {
            var repeatCount = ko.utils.unwrapObservable(valueAccessor());
            ...
            // Remove nodes from end if array is shorter
            for (; lastRepeatCount > repeatCount; lastRepeatCount--) {
                ...
            }
            ...
            // Add nodes to end if array is longer (also initially populates nodes)
            for (; lastRepeatCount < repeatCount; lastRepeatCount++) {
                ...
            }
        }, null, {'disposeWhenNodeIsRemoved': placeholder});
        ...
    }
};

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