2015-11-20 18 views
5

Sto esplorando vue.js e ho una domanda su come un determinato problema può essere risolto.VueJS collega componenti non collegati (come genitore/figlio)

mio componente principale ha la seguente configurazione:

<div class="container"> 
    <div class="stage"> 
     <map :current-time="currentTime" :recording="recording"></map> 
     <player :track="track" :current-time="currentTime"></player> 
    </div> 
    <control-panel :current-time="currentTime"></control-panel> 
</div> 

In sostanza, <player> componente ha <video> elemento interno che caricherà la traccia specificata (con controlli nativi nascosti). In quanto tale, in realtà controllerà lo stato dell'applicazione durante la riproduzione del video (ora corrente, stato di riproduzione, ecc.). Tuttavia, <control-panel> ha una barra di scorrimento e pulsanti che dettano lo stato del video (riproduzione/pausa, ricerca). Ovviamente, l'alterazione di questo stato generale in uno dei componenti influenzerà gli altri due componenti (la mappa avanza anche in base all'ora corrente).

Tuttavia, mi chiedo se sarebbe più sensato e se Vue supporta fornendo i riferimenti ai componenti in modo da poter fornire <control-panel> con un riferimento a <player> in modo che potesse prendere i cambiamenti di stato direttamente da esso.

O questo dovrebbe essere fatto in una sorta di trasmissione a livello globale o trasmissione di eventi? Prima di essere corretto, considera un esempio in cui ci sono due <player> se due <control-panel> s che non sono correlati gerarchicamente, ma un pannelloA funziona con playerA e panelB con playerB. In questo caso, penso che l'opzione di trasmissione cada dal tavolo, giusto?

Tutti i suggerimenti sono benvenuti soprattutto perché sto solo imparando Vue.

Update 1

Così, dopo aver ottenuto un po 'più familiarità con Vue e sentire di nuovo da parte della comunità, penso che è venuta in mente una soluzione intelligente per la sincronizzazione e <player><control-panel> insieme. I miei markup modifiche al seguente:

<div class="container"> 
    <div class="stage"> 
     <map :current-time="currentTime" :recording="recording"></map> 
     <player :track="track" :current-time="currentTime" v-ref:player></player> 
    </div> 
    <control-panel :current-time="currentTime" v-ref:player-controls :player="$refs.player"></control-panel> 
</div> 

Avviso l'aggiunta di v-ref attributi per <player> e <control-panel> nonché :player="$refs.player" attributo in quest'ultimo. Questo mi consente di legare logicamente l'uno all'altro. Nella mia testa, ha senso per il pannello di controllo sapere chi o cosa sta controllando. Ho intenzione di testarlo ulteriormente ma, per ora, questo sembra funzionare.

Come legare insieme <map>, finirò per utilizzare la trasmissione o semplicemente a due vie currentTime aggiornato da <control-panel>. Aggiornerò questo post mentre vado e contrassegnerò la risposta corretta o pubblicherò la mia, se diversa da una qualsiasi delle risposte.

Aggiornamento 2

Leggi la mia risposta qui sotto. Sono stato in grado di risolvere il problema con successo utilizzando l'approccio seguente.

+0

'$ broadcasting' e' $ dispatching' potrebbero ancora funzionare con più giocatori passando id ai componenti tramite 'props' –

+0

Il problema con questo approccio è che il giocatore e il controllo richiederebbero l'id affinché funzionino. Tuttavia, sono componenti potenzialmente indipendenti. Se li implemento in questo modo, la generazione di un componente giocatore richiede al genitore di fornirgli un id (perché quell'id dovrebbe essere fornito a entrambi, in modo che sappiano quali messaggi filtrare). Questo è generalmente un problema con tutti i framework MVVM? Voglio dire, mi piace poter fare questo binding dinamico e roba, ma a volte ho bisogno di un controllo completamente manuale e sembra che non sia così semplice mixare Vue o React con JS. – Vadym

risposta

0

La soluzione implicava l'approccio descritto in Aggiornamento 1. Poiché l'elemento <video> ha una ben ponderata API, la sua traduzione in un componente reattivo è stata piuttosto facile (anche se faticosa).

L'involucro per un elemento video finito creando diversi computed attributi nel seguente modo:

'currentTime': { 
    cache: false, 
    get: function() { 
     return this.$els.player.currentTime; 
    }, 
    set: function (value) { 
     this.$els.player.currentTime = value; 
    } 
} 

Proprietà cache: false deve essere utilizzato perché l'attributo non è legato ad un elemento reattivo e deve essere ricalcolato ogni tempo in cui è stato interrogato l'attributo.

Non rendere intenzionale il componente completamente reattivo. Cioè, avrei potuto definire gli attributi necessari come props con la supposizione che potevano essere forniti da e sincronizzati con il genitore. Tali attributi verrebbero aggiornati internamente ogni volta che l'elemento <video> genererebbe un evento che modifica lo stato.

Ho anche finito di propagare gli eventi dell'elemento <video> al genitore del componente utilizzando il metodo $emit. Ciò è stato fatto perché i componenti hanno semplicemente introdotto HLS e hanno agito come driver di stato. In quanto tale, era accettabile che non fosse completamente reattivo e imitasse il semplice elemento <video>.

Il pannello di controllo ha fatto riferimento con successo al componente del giocatore, come riportato nell'aggiornamento . Avendo ricevuto un handle sul player, è stato facile iscriversi ai suoi eventi con $on e poi semplicemente colpire le sue proprietà calcolate sull'evento che cambiava stato.

Infine, la mappa era un po 'più facile da implementare perché seguiva il flusso più o meno semplice descritto in tutti gli altri esempi di Vue. In realtà, il genitore della mappa teneva traccia del tempo corrente. Questa variabile è stata effettivamente aggiornata dal pannello di controllo utilizzando l'attributo :currentTime.sync="currentTime". Tuttavia, per la mappa, era come se il genitore stesse aggiornando l'ora.

0

Penso che sia una buona idea lasciarli come componenti indipendenti;

si può quindi passare la componente del pannello di controllo ogni volta che vuoi con un altro che utilizza la stessa interfaccia

(come commutazione fuori banda con qualche altro processore di pagamento in un'applicazione e-commerce)

$broadcasting e $dispatching funziona bene anche con più giocatori presenti fino a quando si passa lungo un tasto identificativo con ogni trasmissione/spedizione in modo che ogni componente che riceve il messaggio in grado di determinare immediatamente se è stato inviato per loro.

+0

Sto ancora risolvendo questo.Potrei finire a usare '$ broadcasting' per la sincronizzazione temporale' map'-'video', ma penso di aver trovato un modo intelligente per sincronizzare 'video' e' controls'. Sto aggiornando la mia domanda con le modifiche. – Vadym