37 votes

knockout.js: mettre à jour les liaisons?

quand j'ai injecter de nouveaux éléments dans le DOM après ko.applyBindings(); a été appelé, alors knock-out ne reconnaît pas ces nouveaux éléments. Je peux comprendre pourquoi ce qui se passe, ils ne sont tout simplement pas indexés par knock-out.

Donc, au début je pensais que ce serait résolu simplement en appelant ko.applyBindings() à nouveau, après l'ajout de mon nouveau éléments de, MAIS ensuite j'ai réalisé que pour chaque ko.applyBindings() appel que vous faites, la fonction des événements de me faire virer plusieurs fois. Donc, après l'application de cinq fois, un clic: la liaison sera tiré à cinq reprises, donc ce n'est pas une solution souhaitable ;)

Est-il quelque chose comme ko.updateBindings() ou quelque chose d'autre, de dire knock-out, eh bien... mise à jour de l'élément de liaisons?

salutations, Chris

38voto

ColinE Points 36907

Chaque fois que vous appelez ko.applyBindings de la totalité du DOM est inspecté pour les liaisons. Comme un résultat, vous obtiendrez plusieurs liaisons pour chaque élément si vous faites cela, plus d'une fois. Si vous voulez juste pour lier un nouvel élément du DOM, vous pouvez passer cet élément en tant que paramètre à l' applyBindings fonction de:

ko.applyBindings(viewModelA, document.getElementById("newElement"));

Voir cette question:

KnockoutJS: ko.applyBindings à vue partielle?

7voto

SamStephens Points 2913

Sans savoir ce que vous faites exactement, il semble que vous êtes va dans le mauvais sens à ce sujet. Votre vue doit être dicté par votre modèle de vue. Donc, vous ne devriez pas ajouter directement des éléments du DOM vous devez ensuite appliquer knock-out liaisons.

Au lieu de cela, vous devriez être mise à jour de votre modèle de vue afin de refléter le changement dans la vue, ce qui provoque alors votre nouvel élément à apparaître.

Ainsi, par exemple, pour votre $('body').append('<a href="#" data-bind="click: something">Click me!</a>');, plutôt que d'ajouter l'élément du DOM où le bouton doit être visible, le bouton de contrôle de la visibilité en utilisant le modèle de vue.

Si votre modèle d'affichage comprend

var viewModel = { clickMeAvailable: ko.observable(false) }

Et votre HTML comprend

<a href="#" data-bind="click: something, visible: clickMeAvailable">Click me!</a>

Lorsque l'état de l'application des changements, de sorte cliquez sur le bouton me est disponible, vous n' viewModel.clickMeAvailable(true).

Le point de le faire, et une grande partie de knock-out, est de séparer la logique métier de la présentation. Donc le code qui permet de cliquez-moi disponible ne se soucie pas que sur moi implique un bouton. Tout ce qu'il fait est de mettre à jour viewModel.clickMeAvailable lorsque cliquez sur-moi est disponible.

Par exemple, dire sur moi, c'est un bouton enregistrer qui devrait être disponible lorsqu'un formulaire est rempli valablement. Vous auriez de la cravate sur le bouton enregistrer de la visibilité à une formValid modèle de vue observables.

Mais ensuite, vous décidez de changer les choses pour une fois que le formulaire est valide, un accord juridique qui doit être consenti à l'avant de l'enregistrer. La logique de votre forme ne change pas, il met toujours formValid lorsque le formulaire est valide. Vous serait-il suffit de changer ce qui se produit lorsqu' formValid changements.

Comme lassombra points dans les commentaires sur cette réponse, il ya des cas où directe de manipulation du DOM peut être votre meilleure approche - par exemple un complexe dynamique de la page où vous voulez seulement pour hydrater les parties de la vue qu'elles sont nécessaires. Mais vous êtes renoncer à la séparation des préoccupations knock-out fournit en faisant cela. Être conscient de si vous songez à faire ce compromis.

1voto

Je sais que vous avez demandé il y a longtemps mais je viens de tombé sur un problème similaire. J'ai essayé d'ajouter de nouveaux éléments à conteneurs et de donner à ces un onclick function. Au premier abord essayé les choses que vous avez fait, et même essayé de l'approche ColinE recommandé. Ce n'était pas une solution pratique pour moi, donc j'ai essayé SamStephens approche et est venu avec ce qui workes parfaitement pour moi:

HTML:

<div id="workspace" data-bind="foreach:nodeArr, click:addNode">
<div class="node" data-bind="attr:{id:nodeID},style:{left:nodeX,top:nodeY},text:nodeID, click:$parent.changeColor"></div>
</div>

JavaScript:

<script>
function ViewModel() {
var self = this;
var id = 0;
self.nodeArr = ko.observableArray();
self.addNode = function (data, event) {
    self.nodeArr.push({
        'nodeID': 'node' + id,
        'nodeX' : (event.offsetX - 25) + 'px',
        'nodeY' : (event.offsetY - 10) + 'px'
    })
    id++;
}
self.changeColor = function(data, event){
    event.stopPropagation();
    event.target.style.color = 'green';
    event.target.style.backgroundColor = 'white';
}
}
ko.applyBindings(new ViewModel());
</script>

Vous pouvez jouer avec elle dans le JS Fiddle j'ai fait. Espérons que cela aide toujours 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