Domanda knockout.js: aggiorna i collegamenti?


quando inserisco nuovi elementi nel DOM dopo ko.applyBindings (); è stato chiamato, quindi knockout non riconoscerà questi nuovi elementi. Posso capire perché questo sta accadendo - non sono semplicemente indicizzati per knockout.

Quindi, all'inizio pensavo che sarebbe stato risolto semplicemente chiamando di nuovo ko.applyBindings (), dopo aver aggiunto i miei nuovi elementi, MA poi mi sono reso conto che per ogni chiamata ko.applyBindings (), gli eventi secondo vengono attivati ​​più volte. Quindi, dopo aver applicato cinque volte, un clic: l'associazione verrà licenziata cinque volte, quindi questa non è una soluzione desiderabile;)

C'è qualcosa come ko.updateBindings () o qualcos'altro, per dire knockout a, beh ... aggiornare i binding degli elementi?

saluti, Chris


34
2017-11-26 21:46


origine


risposte:


Ogni volta che invochi ko.applyBindings l'intero DOM viene controllato per le associazioni. Di conseguenza otterrai più associazioni per ciascun elemento se lo fai più di una volta. Se vuoi semplicemente associare un nuovo elemento DOM, puoi passare questo elemento come parametro applyBindings funzione:

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

Vedi questa domanda correlata:

Puoi chiamare ko.applyBindings per associare una vista parziale?


36
2017-11-27 06:47



Senza sapere esattamente cosa stai facendo, sembra che tu stia andando nella direzione sbagliata. La tua vista dovrebbe essere guidata dal tuo modello di vista. Quindi non dovresti aggiungere direttamente elementi DOM a cui devi applicare i collegamenti a eliminazione diretta.

Invece dovresti aggiornare il tuo modello di visualizzazione per riflettere il cambiamento nella vista, che quindi fa apparire il tuo nuovo elemento.

Quindi per esempio, per il tuo $('body').append('<a href="#" data-bind="click: something">Click me!</a>');invece di aggiungere l'elemento DOM quando il pulsante deve essere visibile, controlla la visibilità del pulsante utilizzando il modello di visualizzazione.

Quindi include il tuo modello di visualizzazione

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

E il tuo codice HTML include

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

Quando lo stato dell'applicazione cambia, quindi il pulsante "clic" è disponibile, allora solo viewModel.clickMeAvailable(true).

Il punto di fare questo, e una grande parte del knockout, è separare la logica di business dalla presentazione. Quindi il codice che rende cliccabile su di me non teme che il click me coinvolga un pulsante. Tutto ciò che fa è l'aggiornamento viewModel.clickMeAvailable quando clicchi è disponibile.

Ad esempio, ad esempio, fare clic su di me è un pulsante Salva che dovrebbe essere disponibile quando un modulo viene compilato in modo valido. Legheresti la visibilità del pulsante di salvataggio a a formValid guarda il modello osservabile.

Ma poi decidi di cambiare le cose quindi, dopo che il modulo è valido, appare un accordo legale che deve essere autorizzato prima di salvare. La logica della tua forma non cambia - continua a essere impostata formValid quando il modulo è valido Dovresti solo cambiare cosa succede quando formValid i cambiamenti.

Come sottolinea lassombra nei commenti a questa risposta, ci sono casi in cui la manipolazione diretta del DOM può essere il tuo approccio migliore, ad esempio una pagina dinamica complessa in cui desideri solo idratare parti della vista quando sono necessarie. Ma stai abbandonando parte della separazione delle preoccupazioni che Knockout fornisce in questo modo. Stai attento se stai pensando di fare questo scambio.


7
2017-12-22 03:25



So che l'hai chiesto molto tempo fa, ma mi sono imbattuto in un problema simile. Ho provato ad aggiungere nuovi elementi al contenitore e dare loro una funzione onclick. All'inizio ho provato le cose che hai fatto, e ho anche provato l'approccio Coline  consigliato. Questa non era una soluzione pratica per me, così ci ho provato SamStephens approccio e ne è venuto fuori, che funziona perfettamente per me:

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>

Puoi giocarci con JS Fiddle Ho fatto. Spero che questo aiuti ancora qualcuno.


0
2018-02-06 10:38