2013-11-15 16 views
5

Ho una semplice configurazione GWT per la prova:Come funziona la funzionalità sinkEvent di GWT?

<g:HTMLPanel ui:field="container" width="500px" height="300px"> 
    <g:Label ui:field="inner" text="hello"></g:Label> 
</g:HTMLPanel> 

con i gestori aggiunto:

container.addDomHandler(new ClickHandler() 
{ 
    @Override 
    public void onClick(ClickEvent event) 
    { 
     Window.alert("click on container"); 
    } 
}, ClickEvent.getType()); 

inner.addDomHandler(new ClickHandler() 
{ 
    @Override 
    public void onClick(ClickEvent event) 
    { 
     Window.alert("click on inner"); 
    } 
}, ClickEvent.getType()); 

Ognuno di questi addHandler chiama, come sappiamo dalle fonti,

DOM. sinkEvents (Element elem, int eventBits)

all'interno, e il secondo, secondo i documenti, "Imposta il set corrente di eventi affondato da un dato elemento. Questi eventi saranno licenziati al più vicino {EventListener @link} specificato su uno dei genitori del elemento."

Ma in realtà, se si fa clic sul div interno click saranno licenziati alla sua div genitore in una qualsiasi delle 3 modi:

  • se non è stata impostata alcuna ClickHandlers sul bambino

  • se ho impostato i gestori sul bambino

  • se ho impostato i gestori, ma eliminato l'affondamento di ClickEv ent con

DOM.sinkEvents (inner.getElement(), DOM.getEventsSunk (getElement()) & ~ Event.getTypeInt (ClickEvent.getType() getName()).);

Perché questo accade e qual è il vero ruolo di affondare gli eventi? Perché l'aggiunta di un gestore è correlata agli eventi di sinking, ovvero per attivare lo stesso evento su padre dell'elemento specificato? E 'possibile impedire a tutti i gestori, aggiunti al widget dato di chiamare senza rimuoverli esplicitamente? Cioè c'è un modo per interrompere l'elaborazione di tutti gli eventi su alcuni widget?

risposta

7

Primo, sinkEvent riguarda l'aggiunta del gestore di eventi nativo sull'elemento, come spiegato nello GWT wiki.

Quello che stai vedendo è il bubbling degli eventi, che è il modo in cui gli eventi funzionano nei browser: ci sono 2 fasi durante la spedizione di un evento: la fase di acquisizione (non implementata nei vecchi IE) consente a qualsiasi elemento antenato di catturare l'evento prima di esso raggiunge il suo obiettivo, quindi nella fase di bubbling l'evento bolle su nella gerarchia DOM. Quindi, se ascolti i clic su HTMLPanel, riceverai anche gli eventi di clic bubbling da Label.

È possibile impedirlo ascoltando l'evento al livello Label e chiamando stopPropagation() in modo che non rispecchi allo HTMLPanel.

+0

Grazie, Thomas. Ma se voglio evitare che qualsiasi evento venga elaborato anche a livello di Label, sembra che tutto ciò di cui ho bisogno sia di azzerare il sunkEvents tramite DOM.sinkEvents (label.getElement(), 0), ho ragione? E posso facilmente tornare indietro aggiungendo la maschera di bit ClickEvent, senza aggiungere/rimuovere i gestori. – KutaBeach

+0

Funzionerebbe ma è un grosso brutto trucco! Che ne dici di testare nel gestore di eventi se hai del lavoro da fare o meno (cioè se sei disabilitato o no)?'sinkEvents' è davvero un'API di basso livello che dovrebbe essere utilizzata solo negli interni dei widget; non scherzare con altri widget o probabilmente li romperesti. –

+0

Questo è quello che ho fatto - aggiunto se la clausola in tutti i miei gestori di eventi per impedire che gli eventi vengano elaborati quando il mio widget è disabilitato. Ma copiare gli incassi dello stesso "se" in 5 gestori non sembra così bello, in realtà ..:/ – KutaBeach

Problemi correlati