knockout.js
Attacchi
Ricerca…
Sintassi
-
<!-- ko if:myObservable --><!-- /ko -->
-
<i data-bind="if:myObservable"></i>
Osservazioni
Che legame c'è
In sostanza, un binding o un binding di dati è un modo per collegare ViewModels ai tuoi Views (template) e viceversa. KnockoutJS utilizza l'associazione dati bidirezionale, il che significa che le modifiche al ViewModel influenzano la vista e le modifiche alla vista possono influenzare ViewModel.
Sotto il cofano (breve panoramica)
I binding sono solo plug-in (script) che ti consentono di risolvere un particolare compito. Questo compito è più frequente che cambiare markup (html) in base al ViewModel.
Ad esempio, un'associazione di text
ti consente di visualizzare il testo e cambiarlo dinamicamente ogni volta che ViewModel cambia.
KnockoutJS è dotato di molti potenti binding e ti consente di estenderlo con i tuoi binding personalizzati.
E soprattutto i collegamenti non sono magici, funzionano secondo una serie di regole e ogni volta che non sei sicuro di ciò che fa un binding, quali parametri ci vogliono o quando aggiornerà la vista puoi fare riferimento al codice sorgente del binding.
Considera il seguente esempio di associazione personalizzata:
ko.bindingHandlers.debug = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
ko.computed(function () {
var value = ko.unwrap(valueAccessor());
console.log({
value: value,
viewModel: viewModel,
bindingContext: bindingContext
});
}, null, { disposeWhenNodeIsRemoved: element });
}
};
- Un'associazione ha un nome -
debug
così puoi usare come segue:
data-bind="debug: 'foo'"
- Il metodo
init
viene chiamato una volta quando viene avviata l'associazione. Il resto degli aggiornamenti è gestito da un anonimo calcolato che viene eliminato quando l'element
viene rimosso. - Il binding stampa per gestire diverse cose: il valore passato nel nostro esempio questo valore è
foo
(questo valore può anche essere osservabile poiché il metodoko.unwrap
è usato per leggerlo), il viewModel corrente e il bindingContext corrente. - Ogni volta che il valore passato cambia, l'associazione stamperà le informazioni aggiornate sulla console.
- Questa associazione non può essere utilizzata con elementi virtuali (nei commenti html), solo su elementi reali, poiché il flag
ko.virtualElements.allowedBindings.debug
non è impostato su true.
Quando usare le parentesi
Senza plug-in aggiuntivi, KnockoutJS avrà solo aggiornamenti live View per le proprietà sul ViewModel che sono osservabili ( observable
regolarmente, ma anche computed
, pureComputed
, observableArray
, ecc.). Un osservabile sarebbe creato in questo modo:
var vm = { name: ko.observable("John") };
In questo caso, vm.name
è una funzione con due "modi" separati:
- Getter:
vm.name()
, senza argomenti, otterrà il valore corrente; - Setter:
vm.name("Johnnyboy")
, con un argomento, imposterà un nuovo valore.
Nei collegamenti dati incorporati è sempre possibile utilizzare il modulo getter e talvolta si possono effettivamente omettere le parentesi e il binding le "aggiunge" in modo efficace. Quindi questi sono equivalenti:
<p data-bind="text: name"></p> ... will work
<p data-bind="text: name()"></p> ... works too
Ma questo fallirà:
<p data-bind="text: 'Hello, ' + name + '!'"></p> ... FAILS!
Perché non appena si vuole "fare" qualcosa prima di passare un valore a un'associazione dati, compresi i confronti di valori, è necessario "ottenere" correttamente i valori per tutti gli osservabili, ad esempio:
<p data-bind="text: 'Hello, ' + name() + '!'"></p> ... works
Vedi anche questo Q & A per maggiori dettagli.
Se / se non
È possibile utilizzare il legame if
per determinare se gli elementi figlio del nodo devono essere creati o meno.
<div class="product-info">
<h2> Product1 </h2>
<img src="../products/product1.jpg"/>
<span data-bind="if:featured">
<span class="featured"></span>
</span>
<span data-bind="ifnot:inStock">
<span class="out-of-stock"></span>
</span>
</div>
<script>
ko.applyBindings({
product: {
featured: ko.observable(true),
inStock: ko.observable(false)
}
});
</script>
L'inverso di if
binding è ifnot
<div data-bind="ifnot: someProperty">...</div>
è equivalente a
<div data-bind="if: !someProperty()">...</div>
A volte, non dovrai controllare la presenza di elementi senza dover creare un contenitore (in genere per gli elementi <li>
in un elemento <ul>
o <option>
all'interno di <select>
)
Knockout abilita questo con la sintassi del flusso di controllo senza contenitore in base ai tag di commento in questo modo:
<select>
<option value="0">fixed option</option>
<!-- ko if: featured-->
<option value="1">featured option</option>
<!-- /ko -->
</select>
Per ciascuno
Simile ai ripetitori utilizzati in altre lingue. Questa associazione ti consentirà di replicare un blocco di html per ogni elemento in una matrice.
<div data-bind="foreach:contacts">
<div class="contact">
<h2 data-bind="text:name">
<p data-bind="text:info">
</div>
</div>
<script type="text/javascript">
var contactViewModel = function (data) {
this.name = ko.observable(data.name);
this.info = ko.observable(data.info);
};
ko.applyBindings({
contacts: [
new contactViewModel({name:'Erik', info:'[email protected]'}),
new contactViewModel({name:'Audrey', info:'[email protected]'})
]
});
</script>
Si noti che quando eseguiamo il looping del nostro contesto diventa l'elemento all'interno dell'array, in questo caso un'istanza di contactViewModel
. All'interno di un foreach
abbiamo anche accesso a
-
$parent
- il modello di visualizzazione che ha creato questa associazione -
$root
- il modello di visualizzazione radice (potrebbe anche essere genitore) -
$data
- i dati a questo indice dell'array -
$index
- l'$index
(osservabile) a base zero dell'oggetto reso
Con
Il binding with
associa l'HTML all'interno del nodo associato a un contesto separato:
<div data-bind="with: subViewModel">
<p data-bind="text: title"></p>
</div>
L'associazione with
associazione può anche essere utilizzata senza un elemento contenitore in cui un elemento contenitore potrebbe non essere appropriato.
<!-- ko with: subViewModel -->
<p data-bind="text: title"></p>
<!-- /ko -->
var vm = {
subViewModel: ko.observable()
};
// Doesn't throw an error on the `text: title`; the `<p>` element
// isn't bound to any context (and even removed from the DOM)
ko.applyBindings(vm);
// Includes the `<p>` element and binds it to our new object
vm.subViewModel({ title: "SubViewModel" });
Il binding with
ha molte somiglianze con il template
o foreach
binding.
Visibile
L'associazione visible
nasconderà un elemento applicando style="display: none;"
ad esso quando l'associazione valuta come falsa.
<input type="text" data-bind="textInput: name"> <span class="error" data-bind="visible: isInvalid">Required!</span>
ko.applyBindings(new ViewModel());
function ViewModel(){
var vm = this;
vm.name = ko.observable("test");
vm.isInvalid = ko.computed(function() {
return vm.name().length == 0;
});
}