transition-group throws error attempting to transition whitespace node, but only with migration build and client-side compiled template
Version
3.2.11
Reproduction link
Steps to reproduce
- Load the CodeSandbox link. Open the CodeSandbox console (using the console link in the bottom left corner of the preview area) and note that a warning about
<TransitionGroup>
has already appeared. - Click the "Toggle transition" button
What is expected?
The transition works (the hidden image appears)
What is actually happening?
An error is thrown when attempting the transition (child.el.getBoundingClientRect is not a function
), and the transition doesn't work. Additionally, a warning is thrown on load (<TransitionGroup> children must be keyed
)
This issue is related to #4621, but it's a much more bizarre version of it. All of the following conditions must be met to reproduce the bug:
- A
<transition-group>
that contains two elements, separated by whitespace, with the first element initially hidden usingv-if
and the second element always shown. Unhiding the first element triggers the error. - The migration build (
@vue/compat
) must be used; the bug doesn't happen if you use the regular non-migration build (vue
) - The component containing the
<transition-group>
must be compiled on the client side. The bug doesn't happen if this component is pre-compiled on the server side. (To make client-side compilation work, the full build must be used rather than the runtime-only build.)
Like in #4621, the bug happens because the TransitionGroup code tries to process a text node as one of the nodes being transitioned, in this case the text node between the two <p>
elements. Text nodes don't have a .getBoundingClientRect()
method, which is what causes the error. The warning about TransitionGroup children needing to be keyed is also caused by the text node (it's checked for a key, and it doesn't have one).
In the real-world use case that revealed this bug (see https://phabricator.wikimedia.org/T289019#7322619 ), the <transition-group>
has tag="div"
set, one of the children is a component instead of a plain tag, and the <transition-group>
is nested inside a <transition>
via another component's slot, but those things don't appear to matter, so I've removed them to simplify the (already complex) minimal reproduction.
It looks like these confusing conditions (only in the migration build and with client-side compilation) are not actually necessary, but instead it looks like this bug is triggered by compilerOptions.whitespace
being set to 'preserve'
(which the migration build does, for client-side compiled templates). The text node that causes this bug is only created when whitespace
is set to 'preserve'
, and is not created when whitespace
is set to 'collapse'
.
as a temporary workaround you can remove the HTML comment before the the whitespace between the two p nodes<p v-if="...">
Apologies, it looks like I accidentally messed up the CodeSandbox; it should be correct now. The template code that triggers this bug is:
<button @click="showImage = !showImage">Toggle transition</button>
<transition-group name="foo-bar" class="foo-bar">
<p key="hello">Hello</p>
<p key="img" v-if="showImage">Image</p>
</transition-group>