2015-06-08 16 views
5

Om, il wrapper clojurescript di React, si dice che sia molto veloce perché sfrutta l'immutabilità. Non riesco a capire in che modo le strutture di dati persistenti possano aiutare qui.In che modo le strutture di dati persistenti aiutano a rendere Om più veloce

Quello che ho capito è che lo stato dell'applicazione è un atomo. Questo stato viene passato a funzioni (componenti om) che restituiscono nodi DOM virtuali, in modo che la creazione di una "patch" delle differenze tra il DOM virtuale attuale e il suo stato precedente sia molto meglio che operare direttamente sul DOM corrente.

Ma dove le strutture dati persistenti possono aiutare qui?

(def app-state (atom {:foo {:counter 0})) 
(om/root click-counter app-state {:target ...}) 

per esempio click-counter rendering un pulsante che se cliccato incrementa il contatore. Così la funzione di transizione è simile al seguente:

(dom/button #js {:onClick #(om/transact! app [:foo :counter] inc)} 
      (str "clicked " (-> app :foo :counter) " times")) 

I undestand questo: quando onClick è ClojureScript eseguito crea una nuova mappa (molto efficiente) come questo:

{:foo {:counter 1}} 

e app-state ora punta alla nuova mappa . A questo punto Om è consapevole che lo stato è cambiato perché è solo questione di un controllo di uguaglianza.

Il problema qui è che Om dovrebbe comunque calcolare la differenza tra l'intero vecchio DOM virtuale e quello nuovo. Non sa che è cambiato solo il contatore.

Dov'è il mio errore?

risposta

4

Quando lo stato dell'app è memorizzato in una struttura ad albero persistente come una mappa, è immediatamente ovvio quali parti dell'albero di stato non sono state modificate e non è necessario aggiornarle. Questo perché qualsiasi modifica a un bambino cambia il genitore. Con le strutture di dati mutevoli, le modifiche ai bambini non devono cambiare i genitori.

Quindi, se il vostro stato si presentava così:

{:part1 [1 2 3 4] 
:part2 [:a :b]} 

e si effettua un nuovo stato con l'aggiunta di qualcosa in part2:

{:part1 [1 2 3 4] 
:part2 [:a :b :c]} 

allora la funzione di confronto può guardare e vedere che il valore nella : parte 1 del vecchio e nuovo stato è lo stesso oggetto e pertanto non può avere alcuna modifica a qualsiasi stato nidificato perché è immutabile.

+0

Grazie. Quindi, solo se un controllo di uguaglianza su un nodo fallisce, è necessario un eventuale re-rendering dei suoi figli. – agori

+1

Se l'uguaglianza fallisce allora è possibile che sia richiesto un rerender, anche se forse no, avresti potuto cambiarlo e poi averlo cambiato. Se passa l'uguaglianza, non è assolutamente necessario * aggiornarlo. –

+0

Il problema che vedo è che con grandi strutture di dati piatte come un vettore di migliaia di elementi (forse un'applicazione simil-excel) e si modifica solo un elemento del vettore: '(def cells (atom (into [] (replicate 1000 {: val: vuoto})))) 'e poi' (scambia! (Assoc-in cells [1: val] 10)) '. Ciò fa in modo che Om controlli tutti gli elementi perché la radice della struttura dati è cambiata e non si sa quale cella è stata modificata. Quindi sembra che tutto dipenda da come si decide di strutturare lo stato dell'applicazione, dato che Om non funziona bene con strutture di dati piatte. – agori

Problemi correlati