Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@click would trigger event other vnode @click event. #6566

Closed
XGHeaven opened this issue Sep 11, 2017 · 4 comments
Closed

@click would trigger event other vnode @click event. #6566

XGHeaven opened this issue Sep 11, 2017 · 4 comments

Comments

@XGHeaven
Copy link

XGHeaven commented Sep 11, 2017

Version

2.4.2

Reproduction link

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

Steps to reproduce

see reproduction link.

What is expected?

When I click Expand is True, then expand to become false. And only countA changed.

What is actually happening?

When I click Expand is Ture, nothing happened.
The countA and countB changed.
I guess when I click, expand changed to false, but immediate the click event triggered. It executes another vnode click event. Then expand changed to true.

And More

  • If I rename the second div to another tag name, such as p, section, no errors occur.
  • If I move click event from i tag to parent div tag in the first div, no errors occur
@Kingwl
Copy link
Member

Kingwl commented Sep 11, 2017

qq20170911-185025
seems normal

@yyx990803
Copy link
Member

Your repro is working as intended...

@XGHeaven
Copy link
Author

XGHeaven commented Sep 11, 2017

@Kingwl @yyx990803 Sorry about that. I test others case and forgot to change back.

The important code is

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

There is four case:

  • click event listen on block 1 and block2, works well
  • click event listen on element 1 and element 2, works well
  • click event listen on block 1 and element 2, change expand to true is ok. But cannot change back.
  • click event listen on element 1 and block 2, cannot change expand to false. But can change expand to true.

@yyx990803 yyx990803 added bug and removed need repro labels Sep 13, 2017
@yyx990803
Copy link
Member

So, this happens because:

  • The inner click event on <i> fires, triggering a 1st update on nextTick (microtask)
  • The microtask is processed before the event bubbles to the outer div. During the update, a click listener is added to the outer div.
  • Because the DOM structure is the same, both the outer div and the inner element are reused.
  • The event finally reaches outer div, triggers the listener added by the 1st update, in turn triggering a 2nd update.

This is quite tricky in fix, and other libs that leverages microtask for update queueing also have this problem (e.g. Preact). React doesn't seem to have this problem because they use a synthetic event system (probably due to edge cases like this).

To work around it, you can simply give the two outer divs different keys to force them to be replaced during updates. This would prevent the bubbled event to be picked up:

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

ztlevi pushed a commit to ztlevi/vue that referenced this issue Feb 14, 2018
yyx990803 added a commit that referenced this issue Dec 20, 2018
This also fixes async edge case #6566 where events propagate too slow
and incorrectly trigger handlers post-patch.
f2009 pushed a commit to f2009/vue that referenced this issue Jan 25, 2019
f2009 pushed a commit to f2009/vue that referenced this issue Jan 25, 2019
This also fixes async edge case vuejs#6566 where events propagate too slow
and incorrectly trigger handlers post-patch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants