Je crée des fonctionnalités sur une page Web que l'utilisateur peut exécuter plusieurs fois. Grâce à l'action de l'utilisateur, un objet / modèle est créé et appliqué au HTML à l'aide de ko.applyBindings ().
Le HTML lié aux données est créé via des modèles jQuery.
Jusqu'ici tout va bien.
Lorsque je répète cette étape en créant un deuxième objet / modèle et en appelant ko.applyBindings (), je rencontre deux problèmes:
- Le balisage montre l'objet / modèle précédent ainsi que le nouvel objet / modèle.
- Une erreur javascript se produit concernant l'une des propriétés de l'objet / modèle, bien qu'elle soit toujours rendue dans le balisage.
Pour contourner ce problème, après le premier passage, j'appelle .empty () de jQuery pour supprimer le modèle HTML qui contient tous les attributs de liaison de données, afin qu'il ne soit plus dans le DOM. Lorsque l'utilisateur démarre le processus pour la deuxième passe, le code HTML lié aux données est de nouveau ajouté au DOM.
Mais comme je l'ai dit, lorsque le HTML est de nouveau ajouté au DOM et lié au nouvel objet / modèle, il inclut toujours les données du premier objet / modèle, et j'obtiens toujours l'erreur JS qui ne se produit pas lors du premier passage.
La conclusion semble être que Knockout tient à ces propriétés liées, même si le balisage est supprimé du DOM.
Donc, ce que je recherche, c'est un moyen de supprimer ces propriétés liées de Knockout; dire à KO qu'il n'y a plus de modèle observable. Y a-t-il un moyen de faire cela?
ÉDITER
Le processus de base est que l'utilisateur télécharge un fichier; le serveur répond alors avec un objet JSON, le HTML lié aux données est ajouté au DOM, puis le modèle d'objet JSON est lié à ce HTML en utilisant
mn.AccountCreationModel = new AccountViewModel(jsonData.Account);
ko.applyBindings(mn.AccountCreationModel);
Une fois que l'utilisateur a effectué certaines sélections sur le modèle, le même objet est renvoyé sur le serveur, le HTML lié aux données est supprimé du DOM, et j'ai alors le JS suivant
mn.AccountCreationModel = null;
Lorsque l'utilisateur souhaite recommencer, toutes ces étapes sont répétées.
J'ai peur que le code soit trop «impliqué» pour faire une démo jsFiddle.
init
fonction dans laquelle vous passez les données à appliquer?Réponses:
Avez-vous essayé d'appeler la méthode de noeud propre de knockout sur votre élément DOM pour éliminer les objets liés en mémoire?
Ensuite, appliquer à nouveau les liaisons knockout sur cet élément uniquement avec vos nouveaux modèles de vue mettrait à jour votre liaison de vue.
la source
delete
à certaines touches sur les éléments dom eux-mêmes, ce qui est apparemment l'endroit où toute la magie knockout est stockée. Si quelqu'un a une source sur la documentation, je serais très obligé.Pour un projet sur
ko.unapplyBindings
lequel je travaille, j'ai écrit une fonction simple qui accepte un nœud jQuery et le booléen remove. Il dissocie d'abord tous les événements jQuery car lako.cleanNode
méthode ne s'en charge pas. J'ai testé des fuites de mémoire et cela semble fonctionner très bien.la source
ko.cleanNode()
appelé et pas le html entier remplacé.Vous pouvez essayer d'utiliser la liaison avec que Knockout offre: http://knockoutjs.com/documentation/with-binding.html L'idée est d'utiliser des liaisons d'application une fois, et chaque fois que vos données changent, mettez simplement à jour votre modèle.
Disons que vous avez un storeViewModel de modèle de vue de niveau supérieur, votre panier représenté par cartViewModel, et une liste d'articles dans ce panier - disons cartItemsViewModel.
Vous lieriez le modèle de niveau supérieur - le storeViewModel à la page entière. Ensuite, vous pouvez séparer les parties de votre page qui sont responsables des articles du panier ou du panier.
Supposons que le cartItemsViewModel a la structure suivante:
Le cartItemsViewModel peut être vide au début.
Les étapes ressembleraient à ceci:
Définissez les liaisons en html. Séparez la liaison cartItemsViewModel.
Le modèle de magasin provient de votre serveur (ou est créé de toute autre manière).
var storeViewModel = ko.mapping.fromJS(modelFromServer)
Définissez des modèles vides sur votre modèle de vue de niveau supérieur. Ensuite, une structure de ce modèle peut être mise à jour avec des données réelles.
Liez le modèle de vue de niveau supérieur.
ko.applyBindings(storeViewModel);
Lorsque l'objet cartItemsViewModel est disponible, affectez-le à l'espace réservé précédemment défini.
storeViewModel.cartItemsViewModel(actualCartItemsModel);
Si vous souhaitez effacer les articles du panier:
storeViewModel.cartItemsViewModel(null);
Knockout s'occupera du html - c'est-à-dire qu'il apparaîtra lorsque le modèle n'est pas vide et que le contenu de div (celui avec le "avec liaison") disparaîtra.
la source
Je dois appeler ko.applyBinding chaque fois que vous cliquez sur le bouton de recherche, et les données filtrées sont renvoyées par le serveur, et dans ce cas, je travaille pour moi sans utiliser ko.cleanNode.
J'ai expérimenté, si nous remplaçons foreach par template, cela devrait fonctionner correctement en cas de collections / observableArray.
Vous pouvez trouver ce scénario utile.
la source
Au lieu d'utiliser les fonctions internes de KO et de gérer la suppression du gestionnaire d'événements de couverture de JQuery, une bien meilleure idée consiste à utiliser
with
ou lestemplate
liaisons. Lorsque vous faites cela, ko recrée cette partie du DOM et elle est donc automatiquement nettoyée. Ceci est également recommandé, voir ici: https://stackoverflow.com/a/15069509/207661 .la source
Je pense qu'il serait peut-être préférable de conserver la liaison tout le temps et de simplement mettre à jour les données qui y sont associées. J'ai rencontré ce problème et j'ai constaté que le simple fait d'appeler en utilisant la
.resetAll()
méthode du tableau dans lequel je conservais mes données était le moyen le plus efficace de le faire.En gros, vous pouvez commencer avec une variable globale qui contient des données à rendre via le ViewModel:
Il m'a fallu un certain temps pour réaliser que je ne pouvais pas simplement créer
myLiveData
un tableau normal - lako.oberservableArray
partie était importante.Ensuite, vous pouvez continuer et faire ce que vous voulez
myLiveData
. Par exemple, passez un$.getJSON
appel:Une fois que vous avez fait cela, vous pouvez continuer et appliquer des liaisons en utilisant votre ViewModel comme d'habitude:
Ensuite, dans le HTML, utilisez simplement
myData
comme vous le feriez normalement.De cette façon, vous pouvez simplement utiliser myLiveData à partir de n'importe quelle fonction. Par exemple, si vous souhaitez mettre à jour toutes les quelques secondes, enveloppez simplement cette
$.getJSON
ligne dans une fonction et appelezsetInterval
-la. Vous n'aurez jamais besoin de supprimer la liaison tant que vous vous souviendrez de conserver lamyLiveData.removeAll();
ligne.À moins que vos données ne soient vraiment énormes, l'utilisateur ne pourra même pas remarquer le temps entre la réinitialisation du tableau et l'ajout des données les plus récentes.
la source
J'ai eu un problème de fuite de mémoire récemment et
ko.cleanNode(element);
je ne le ferais pas pour moi - je l'ko.removeNode(element);
ai fait. Fuite de mémoire Javascript + Knockout.js - Comment s'assurer que l'objet est détruit?la source
Avez-vous pensé à cela:
J'ai trouvé ça parce que dans Knockout, j'ai trouvé ce code
Donc, pour moi, ce n'est pas vraiment un problème qui est déjà lié, c'est que l'erreur n'a pas été détectée et traitée ...
la source
J'ai trouvé que si le modèle de vue contient de nombreuses liaisons div, la meilleure façon de l'effacer
ko.applyBindings(new someModelView);
est d'utiliser:ko.cleanNode($("body")[0]);
Cela vous permet d'appeler un nouveauko.applyBindings(new someModelView2);
dynamiquement sans vous soucier du modèle de vue précédent toujours lié.la source
$("body")[0]
estdocument.body
.