Vue: @click akan memicu peristiwa vnode @click peristiwa lainnya.

Dibuat pada 11 Sep 2017  ·  4Komentar  ·  Sumber: vuejs/vue

Versi: kapan

2.4.2

Tautan reproduksi

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

Langkah-langkah untuk mereproduksi

lihat tautan reproduksi.

Apa yang diharapkan?

Saat saya mengklik Expand is True , lalu expand menjadi false . Dan hanya countA berubah.

Apa yang sebenarnya terjadi?

Ketika saya mengklik Expand is Ture , tidak terjadi apa-apa.
countA dan countB berubah.
Saya kira ketika saya mengklik, expand berubah menjadi false , tetapi peristiwa klik segera terpicu. Ini menjalankan acara klik vnode lain. Kemudian luaskan diubah menjadi true .

Dan Lainnya

  • Jika saya mengganti nama div kedua menjadi nama tag lain, seperti p , section , tidak ada kesalahan yang terjadi.
  • Jika saya memindahkan peristiwa klik dari i tag ke induk div tag di div pertama, tidak ada kesalahan yang terjadi
bug improvement

Komentar yang paling membantu

Jadi, ini terjadi karena:

  • Peristiwa klik dalam pada <i> diaktifkan, memicu pembaruan pertama pada nextTick (tugas mikro)
  • Microtask diproses sebelum event menggelembung ke div luar . Selama pembaruan, pemroses klik ditambahkan ke div luar.
  • Karena struktur DOM sama, div luar dan elemen dalam digunakan kembali.
  • Peristiwa tersebut akhirnya mencapai div luar, memicu pemroses yang ditambahkan oleh pembaruan pertama, yang pada gilirannya memicu pembaruan kedua.

Ini cukup rumit dalam memperbaikinya, dan libs lain yang memanfaatkan microtask untuk antrian pembaruan juga mengalami masalah ini (mis. Preact). React sepertinya tidak mengalami masalah ini karena mereka menggunakan sistem event sintetis (mungkin karena kasus edge seperti ini).

Untuk mengatasinya, Anda cukup memberikan dua div luar kunci yang berbeda untuk memaksa mereka diganti selama pembaruan. Ini akan mencegah acara yang menggelegak diambil:

<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>

Semua 4 komentar

qq20170911-185025
terlihat normal

Repro Anda berfungsi sebagaimana mestinya ...

@Kingwl @ yyx990803 Maaf tentang itu. Saya menguji kasus lain dan lupa mengganti kembali.

Kode penting adalah

<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>

Ada empat kasus:

  • klik acara dengarkan block 1 dan block2 , berfungsi dengan baik
  • klik acara dengarkan element 1 dan element 2 , berfungsi dengan baik
  • klik event dengarkan block 1 dan element 2 , ubah expand menjadi true ok. Tapi tidak bisa berubah kembali.
  • klik acara dengarkan element 1 dan block 2 , tidak dapat mengubah expand menjadi false. Tetapi dapat mengubah expand menjadi true.

Jadi, ini terjadi karena:

  • Peristiwa klik dalam pada <i> diaktifkan, memicu pembaruan pertama pada nextTick (tugas mikro)
  • Microtask diproses sebelum event menggelembung ke div luar . Selama pembaruan, pemroses klik ditambahkan ke div luar.
  • Karena struktur DOM sama, div luar dan elemen dalam digunakan kembali.
  • Peristiwa tersebut akhirnya mencapai div luar, memicu pemroses yang ditambahkan oleh pembaruan pertama, yang pada gilirannya memicu pembaruan kedua.

Ini cukup rumit dalam memperbaikinya, dan libs lain yang memanfaatkan microtask untuk antrian pembaruan juga mengalami masalah ini (mis. Preact). React sepertinya tidak mengalami masalah ini karena mereka menggunakan sistem event sintetis (mungkin karena kasus edge seperti ini).

Untuk mengatasinya, Anda cukup memberikan dua div luar kunci yang berbeda untuk memaksa mereka diganti selama pembaruan. Ini akan mencegah acara yang menggelegak diambil:

<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>
Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

bdedardel picture bdedardel  ·  3Komentar

loki0609 picture loki0609  ·  3Komentar

paceband picture paceband  ·  3Komentar

aviggngyv picture aviggngyv  ·  3Komentar

gkiely picture gkiely  ·  3Komentar