Vue: @click desencadenaría el evento otro evento vnode @click.

Creado en 11 sept. 2017  ·  4Comentarios  ·  Fuente: vuejs/vue

Versión

2.4.2

Enlace de reproducción

https://jsbin.com/qejofexedo/edit?html , js, salida

pasos para reproducir

ver enlace de reproducción.

¿Lo que es esperado?

Cuando hago clic en Expand is True , luego expand para convertirme en false . Y solo countA cambió.

¿Qué está pasando realmente?

Cuando hago clic en Expand is Ture , no pasó nada.
Los countA y countB cambiaron.
Supongo que cuando hago clic, expand cambió a false , pero inmediatamente se activó el evento de clic. Ejecuta otro evento de clic de vnode. Luego expanda cambiado a true .

Y más

  • Si cambio el nombre del segundo div a otro nombre de etiqueta, como p , section , no se producen errores.
  • Si muevo el evento de clic de la etiqueta i etiqueta principal div en el primer div, no se producen errores
bug improvement

Comentario más útil

Entonces, esto sucede porque:

  • El evento de clic interno en <i> activa, lo que desencadena una primera actualización en nextTick (microtask)
  • La microtarea se procesa antes de que el evento burbujee en el div externo . Durante la actualización, se agrega un detector de clics al div externo.
  • Debido a que la estructura DOM es la misma, tanto el div externo como el elemento interno se reutilizan.
  • El evento finalmente alcanza el div externo, activa el oyente agregado por la primera actualización, lo que a su vez activa una segunda actualización.

Esto es bastante complicado de solucionar, y otras bibliotecas que aprovechan la microtarea para la cola de actualización también tienen este problema (por ejemplo, Preact). React no parece tener este problema porque usan un sistema de eventos sintéticos (probablemente debido a casos extremos como este).

Para solucionarlo, simplemente puede darles a los dos div externos claves diferentes para forzar su reemplazo durante las actualizaciones. Esto evitaría que se recoja el evento burbujeado:

<div class="header" v-if="expand" key="1"> // block 1
  <i @click="expand = false, countA++">Expand is True</i> // element 1
</div>
<div class="expand" v-if="!expand" @click="expand = true, countB++" key="2"> // block 2
  <i>Expand is False</i> // element 2
</div>

Todos 4 comentarios

qq20170911-185025
parece normal

Tu reproducción funciona según lo previsto ...

@Kingwl @ yyx990803 Lo siento. Probé el caso de otros y olvidé volver a cambiar.

El código importante es

<div class="header" v-if="expand"> // block 1
  <i @click="expand = false, countA++">Expand is True</i> // element 1
</div>
<div class="expand" v-if="!expand" @click="expand = true, countB++"> // block 2
  <i>Expand is False</i> // element 2
</div>

Hay cuatro casos:

  • haga clic en evento escuchar en block 1 y block2 , funciona bien
  • haga clic en el evento escuchar en element 1 y element 2 , funciona bien
  • haga clic en el evento escuchar en block 1 y element 2 , cambie expand a verdadero está bien. Pero no puedo volver atrás.
  • haga clic en el evento escuchar en element 1 y block 2 , no se puede cambiar expand a falso. Pero puede cambiar expand a verdadero.

Entonces, esto sucede porque:

  • El evento de clic interno en <i> activa, lo que desencadena una primera actualización en nextTick (microtask)
  • La microtarea se procesa antes de que el evento burbujee en el div externo . Durante la actualización, se agrega un detector de clics al div externo.
  • Debido a que la estructura DOM es la misma, tanto el div externo como el elemento interno se reutilizan.
  • El evento finalmente alcanza el div externo, activa el oyente agregado por la primera actualización, lo que a su vez activa una segunda actualización.

Esto es bastante complicado de solucionar, y otras bibliotecas que aprovechan la microtarea para la cola de actualización también tienen este problema (por ejemplo, Preact). React no parece tener este problema porque usan un sistema de eventos sintéticos (probablemente debido a casos extremos como este).

Para solucionarlo, simplemente puede darles a los dos div externos claves diferentes para forzar su reemplazo durante las actualizaciones. Esto evitaría que se recoja el evento burbujeado:

<div class="header" v-if="expand" key="1"> // block 1
  <i @click="expand = false, countA++">Expand is True</i> // element 1
</div>
<div class="expand" v-if="!expand" @click="expand = true, countB++" key="2"> // block 2
  <i>Expand is False</i> // element 2
</div>
¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

aviggngyv picture aviggngyv  ·  3Comentarios

franciscolourenco picture franciscolourenco  ·  3Comentarios

paulpflug picture paulpflug  ·  3Comentarios

hiendv picture hiendv  ·  3Comentarios

paceband picture paceband  ·  3Comentarios