Component inside <Transition> renders non-element root node that cannot be ani..

8,225 阅读1分钟

问题现象,如下图所示,左侧“发版配置”菜单对应的路由是/release-config/index,在这个路径上刷新页面时候

右侧的内容(组件)是可以加载出来的。

image.png

但是当点击左侧的其他菜单,比如“消息通知”时,消息通知所对应的右侧内容(组件)就加载不出来了,

image.png

而且点回“发版配置”菜单时,发版配置对应的右侧内容(组件)也加载不出来了。

image.png

在控制台可以看到如下的Vue warn:

image.png

Component inside <Transition> renders non-element root node that cannot be animated.

这个warn是因为组件中包裹的不是一个单节点元素。

确实,我们在<router-view>中使用了<transition>

<router-view v-slot="{ Component, route }">
  <transition name="zoom-fade" mode="out-in" appear>
    <keep-alive>
      <component :is="Component" />
    </keep-alive>
  </transition>
</router-view>

<keep-alive><component>都不会创建真实的DOM元素,直接包裹在<transition>中的,就是我们自己写的组件,也就是传给<component>is属性的Component

出现问题的“发版配置”菜单所对应的右侧内容组件是这样的:

image.png

为了方便看,我把代码折叠了,<template>模板中等于使用了vue3的Fragments特性,存在两个root节点。这就是<transition>报错的原因。

既然是<transition>中不能有多个root元素,那解决方法就有两个,

  1. 不使用<transition>
  2. 把我们的组件都包裹成单root节点

但是还是想用<transition>带来的动画效果,因此采用办法2。

最后再重新看下vue3文档关于<transition>的介绍:

<transition> serve as transition effects for single element/component. The <transition> only applies the transition behavior to the wrapped content inside;

<transition>只能用于单元素/组件之上。