Skip to content

Instantly share code, notes, and snippets.

@yyx990803
Last active July 13, 2022 12:39
  • Star 21 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save yyx990803/d1a0eaac052654f93a1ccaab072076dd to your computer and use it in GitHub Desktop.

2.6 Internal Change: Reverting nextTick to Always Use Microtask

The Original Problem

When Vue detects data mutation, it asynchronously defer DOM updates to the next "tick" so that multiple mutations trigger only one update cycle. In versions before 2.5, Vue has been deferring updates using what is known as the "Microtask" (as explained in this blog post).

This works fine in most situations, but we discovered an edge case:

  1. Given two nested elements, "outer" and "inner";
  2. "inner" has a click event handler which triggers an update
  3. the update attaches another click event listener to "outer"

Step 3, when executed in a Microtask, happens before the click event bubbles up to "outer". As a result, the event listener on "outer" is triggered by the same event that caused it to be attached!

This is a very rare edge case, but it is very difficult for the user to figure out what is going on when they run into it.

The Use of Macrotask in 2.5

In 2.5.0, in order to work around this edge case, we changed the internal implementation of nextTick to use Macrotasks instead of Microtasks when the update is triggered inside an event handler. However, the change has actually led to more problems of its own, outweighing the benefit of the fix.

Reverting to Microtask in 2.6 and Potential Side Effects

In 2.6, we managed to find a simpler fix for the edge case, which allowed us to revert nextTick back to using Microtasks in all cases.

Since the new fix relies on checking DOM event timestamps to avoid unnecessary handler invocations, there is a very slight chance to cause some existing tests to fail: if a test creates a mock event before a test component is mounted, and uses that event to trigger handlers on the test component, it will not fire. This should be really rare in practice though (we found exactly one case in Vuetify's entire test suite).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment