广告
返回顶部
首页 > 资讯 > 精选 >Vue3过渡动画的示例分析
  • 311
分享到

Vue3过渡动画的示例分析

2023-06-22 05:06:03 311人浏览 安东尼
摘要

这期内容当中小编将会给大家带来有关vue3过渡动画的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。背景在我的 《Vue 3 开发企业级音乐 App》课程问答区,有个同学提了个问题,在歌手列表到歌手

这期内容当中小编将会给大家带来有关vue3过渡动画的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

背景

在我的 《Vue 3 开发企业级音乐 App》课程问答区,有个同学提了个问题,在歌手列表到歌手详情页面到转场动画中,只有进入动画,却没有离场动画:

Vue3过渡动画的示例分析

该学生确实在这个问题上研究了有一段时间,而且从他的描述,我一时半会儿也想不出哪有问题,于是让他把代码传到 GitHub 上,毕竟直接从代码层面定位问题是最靠谱的。

问题定位

一般遇到此类问题的时候,我的第一反应是他用的 Vue 3 版本可能有问题,毕竟 Vue 3 还在不断迭代过程,某个版本有一些小 bug 是很正常的,于是我把他的项目的 Vue 3 版本升级到了最新的 3.2.26。

但运行后发现,该问题仍然存在。我感到有些困惑,于是跑了一下自己课程项目源码,并没有复现该问题,然后我又把自己课程项目的 Vue 3 版本也升级到最新,仍然没有复现该问题。

通过上述分析,我基本排除了 Vue 3 版本的问题。本质上说,从歌手页面切换到歌手详情页无非就是打开歌手详情页这个二级路由页面,而从歌手详情页退回到歌手页面无非就是移除歌手详情页这个二级路由页面。于是我开始对比两边项目的歌手页面以及详情页的源码:

<!-- singer.vue --><template><div class="singer" v-loading="!singers.length">  <index-list    :data="singers"    @select="selectSinger"  ></index-list>  <!-- 用router-view去承载二级路由 --><!--  <router-view :singer="selectedSinger"></router-view>-->  <!-- vue3需要在router-view中使用transition, appear进入时候也会有动画 -->  <router-view v-slot="{ Component }"><!--  singer-detail返回动画无效 研究  -->    <transition appear name="slide">      <!-- component动态组件Component就是作用域插槽中的一个属性,这个是由router-view这个组提供的       Component就是你的路由表中的路由组件       exclude="singer-detail"排除不缓存数据的组件否则会缓存数据导致每次数据都不重新请求       -->        <component :is="Component"                   :singer="selectedSinger"        ></component>    </transition>  </router-view></div></template><!-- singer-detail.vue --><template>  <!-- 因为通过二级路由实现,所以放在views下 -->  <section class="singer-detail">    <music-list      :songs="songs"      :title="title"      :pic="pic"      :loading="loading"    ></music-list>  </section></template>

上边是学生的代码,接下来贴一下我项目的源码:

<!-- singer.vue --><template>  <div class="singer" v-loading="!singers.length">    <index-list      :data="singers"      @select="selectSinger"    ></index-list>    <router-view v-slot="{ Component }">      <transition appear name="slide">        <component :is="Component" :data="selectedSinger"/>      </transition>    </router-view>  </div></template><!-- singer-detail.vue --><template>  <div class="singer-detail">    <music-list      :songs="songs"      :title="title"      :pic="pic"      :loading="loading"    ></music-list>  </div></template>

经过对比,我感觉两边的源码差别并不大,除了该学生会用注释做一些学习笔记。一时间难以找出问题,于是我祭出了杀手锏——调试源码。因为毕竟对于 Vue 3 过渡动画的实现原理,我还是如数家珍的。

如果执行了退出过渡动画,则一定会执行 transition 组件包裹的子节点解析出的 leave 钩子函数。

于是我在 leave 钩子函数内部加了个 debugger 断点:

// @vue/runtime-core/dist/runtime.core-bundler.esm.jsleave(el, remove) {  debugger  const key = String(vnode.key);  if (el._enterCb) {    el._enterCb(true );  }  // ...}

接着运行项目,当我从歌手详情页回退到歌手页面的时候,发现并没有进入 debugger 断点,也就意味着 leave 钩子函数压根没有执行。

再往前追溯,对于即将卸载的节点,执行其 leave 钩子函数的时机是在执行 remove 函数时,于是我在 remove 函数内部打上断点:

// @vue/runtime-core/dist/runtime.core-bundler.esm.jsconst remove = vnode => {  debugger  const { type, el, anchor, transition } = vnode;  if (type === Fragment) {    removeFragment(el, anchor);    return;  }  if (type === Static) {    removeStaticNode(vnode);    return;  }  const perfORMRemove = () => {    hostRemove(el);    if (transition && !transition.persisted && transition.afterLeave) {      transition.afterLeave();    }  };  if (vnode.shapeFlag & 1  &&    transition &&    !transition.persisted) {    const { leave, delayLeave } = transition;    const performLeave = () => leave(el, performRemove);    if (delayLeave) {      delayLeave(vnode.el, performRemove, performLeave);    }    else {      performLeave();    }  }  else {    performRemove();  }};

接着再次运行项目,当我从歌手详情页回退到歌手页面的时候,虽然进入了断点,但也发现了一些代码的逻辑问题:从 vnode 解析到了对应的 transition 对象,由于其对应的 type 是 Fragment,执行进入了下面这段逻辑:

if (type === Fragment) {  removeFragment(el, anchor);  return;}

直接返回并没有执行后续 transition 对象的 leave 钩子函数。我继续查看 vnode 的值,发现它有两个子节点,一个注释节点和一个 section 节点。我恍然大悟,原来是学生写的注释导致的问题:

<!-- singer-detail.vue --><template>  <!-- 因为通过二级路由实现,所以放在views下 -->  <section class="singer-detail">    <music-list      :songs="songs"      :title="title"      :pic="pic"      :loading="loading"    ></music-list>  </section></template>

在 Vue 的模版解析中,遇到 html 注释,也会把它解析成一个注释节点,可以借助 Vue 3 的模版导出工具看一下它编译后的结果:

import { createCommentVNode as _createCommentVNode, resolveComponent as _resolveComponent, createVNode as _createVNode, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"const _hoisted_1 = { class: "singer-detail" }function render(_ctx, _cache) {  const _component_music_list = _resolveComponent("music-list")  return (_openBlock(), _createElementBlock(_Fragment, null, [    _createCommentVNode(" 因为通过二级路由实现,所以放在views下 "),    _createElementVNode("section", _hoisted_1, [      _createVNode(_component_music_list, {        songs: _ctx.songs,        title: _ctx.title,        pic: _ctx.pic,        loading: _ctx.loading      }, null, 8 , ["songs", "title", "pic", "loading"])    ])  ], 2112 ))}

由于 Vue 3 支持了模版可以有不止一个的根节点,上述模版的根就会被解析成一个 Fragment 节点,这就导致了该组件在移除的时候并不会执行对应的过渡动画。

进一步分析

那么为啥 Fragment 节点就不需要过渡动画呢?我找到了代码对应的提交注释:

fix(fragment): perform direct remove when removing fragments This avoids trying to grab .el from hoisted child nodes (which can be created by another instance), and also skips transition check since fragment children cannot have transitions.

注释给的解释就是 Fragment 节点不可以有 transition 过渡。但这里还有一个问题,为什么这么写不会影响进入过渡动画呢?

因为在运行时执行组件 render 函数渲染组件的子树 subTree 的时候,renderComponentRoot 函数内部做了一些特殊处理:

function renderComponentRoot(instance) {  let result  // ...  // call render funtion to get the result  // attr merging  // in dev mode, comments are preserved, and it's possible for a template  // to have comments along side the root element which makes it a fragment  let root = result;  let setRoot = undefined;  if ((process.env.NODE_ENV !== 'production') &&    result.patchFlag > 0 &&    result.patchFlag & 2048 ) {    [root, setRoot] = getChildRoot(result);  }  // inherit transition data  if (vnode.transition) {    // ...    root.transition = vnode.transition;  }  return result}

在通过执行组件实例的 render 方法拿到渲染的子树后,在开发环境下通过 getChildRoot 函数对注释节点做了一层过滤,得到结果 root,并且给它的根节点继承了其 parent vnode 的 transition 对象。但是注意到,整个 renderComponentRoot 返回的还是 result 对象。

对于我们的示例 SingerDetil 歌手详情组件,它的子树 vnode 是一个 Fragment,但是在执行 renderComponentRoot 的时候,由于第一个节点是注释节点,则被过滤,只有后面的实体节点 singer-detail 对应的 vnode 才有 transition 属性,因此它有进入过渡动画。

但是在组件移除的时候,由于组件的子树 vnode 是一个 Fragment,因此不会有离开过渡动画。

找到了 bug 的原因后,修复就很简单了,直接把注释节点删除即可,当然生产环境不会有该问题,因为在默认情况下,生产环境会删除注释节点。 

上述就是小编为大家分享的Vue3过渡动画的示例分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网精选频道。

--结束END--

本文标题: Vue3过渡动画的示例分析

本文链接: https://www.lsjlt.com/news/302808.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Vue3过渡动画的示例分析
    这期内容当中小编将会给大家带来有关Vue3过渡动画的示例分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。背景在我的 《Vue 3 开发企业级音乐 App》课程问答区,有个同学提了个问题,在歌手列表到歌手...
    99+
    2023-06-22
  • vue3中过渡动画的示例分析
    这篇文章主要介绍了vue3中过渡动画的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。一、vue中动画简单介绍在vue中如果一些过程不存在动画效果,则表现出来的结果是比...
    99+
    2023-06-29
  • Bootstrap过渡动画的示例分析
    这篇文章主要为大家展示了“Bootstrap过渡动画的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Bootstrap过渡动画的示例分析”这篇文章吧。动...
    99+
    2022-10-19
  • CSS3中变形、过渡、动画属性的示例分析
    小编给大家分享一下CSS3中变形、过渡、动画属性的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! css3中制作动画的...
    99+
    2022-10-19
  • Vue3过渡动画的方法
    本篇内容主要讲解“Vue3过渡动画的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue3过渡动画的方法”吧!Vue的transition组件Vue中中提供了transition组件,该组件...
    99+
    2023-06-29
  • vue3过渡动画的详解
    目录一、vue中动画简单介绍二、vue的transition动画三、transition组件的实现原理四、transition过渡动画的class属性五、class的添加时机和命名规...
    99+
    2022-11-13
  • Vue Router过渡动效的示例分析
    这篇文章给大家分享的是有关Vue Router过渡动效的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Vue的优点Vue具体轻量级框架、简单易学、双向数据绑定、组件化、数据和结构的分离、虚拟DOM、运行速...
    99+
    2023-06-14
  • css3过渡属性的示例分析
    这篇文章将为大家详细讲解有关css3过渡属性的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。     多项改变    ...
    99+
    2022-10-19
  • 十分钟带你快速上手Vue3过渡动画
    目录写在前面Vue的transition组件过渡democlass的命名规则使用animation过渡模式appear属性animate.css库的使用使用动画序列使用自定义过渡cl...
    99+
    2022-11-13
  • vue.js过渡css类名的示例分析
    这篇文章主要为大家展示了“vue.js过渡css类名的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“vue.js过渡css类名的示例分析”这篇文章吧。首...
    99+
    2022-10-19
  • 关于Vue3过渡动画的踩坑记录
    目录背景问题定位进一步分析总结背景 在我的 《Vue 3 开发企业级音乐 App》课程问答区,有个同学提了个问题,在歌手列表到歌手详情页面到转场动画中,只有进入动画,却没有离场动画:...
    99+
    2022-11-12
  • css动画的示例分析
    这篇文章主要为大家展示了“css动画的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“css动画的示例分析”这篇文章吧。   CSS3动画是什么?  ...
    99+
    2022-10-19
  • vue巧用过渡效果的示例分析
    这篇文章主要介绍vue巧用过渡效果的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!vue提供的了transition组件来实现组件的过渡和路由的过渡,合理使用这个组建可以让我...
    99+
    2022-10-19
  • Vue 动画效果、过渡效果的示例代码
    目录动画效果过渡效果单个元素多个元素Animate.css总结todolist 增加动画效果动画效果 新建 Test.vue <template> <div&...
    99+
    2022-11-13
  • Vue3之使用js实现动画示例解析
    目录概述实例解析总结概述 动画的实现其实不仅可以使用CSS的方式实现,而且还可以使用js的方式实现,二者有啥区别呢?CSS更加注重动画的展现,性能更好,而js的方式性能稍微差点,但...
    99+
    2023-05-14
    Vue3使用js实现动画 Vue3 js实现动画
  • Angular4.0动画操作的示例分析
    这篇文章主要为大家展示了“Angular4.0动画操作的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Angular4.0动画操作的示例分析”这篇文章吧...
    99+
    2022-10-19
  • loading动画特效的示例分析
    这篇文章给大家分享的是有关loading动画特效的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。代码示例<!DOCTYPE html> <ht...
    99+
    2022-10-19
  • Android动画之小球拟合动画的示例分析
    这篇文章给大家分享的是有关Android动画之小球拟合动画的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Android动画之小球拟合动画实例实现效果:动画组成:通过三阶贝塞尔曲线来拟合圆,拟合系数的由来...
    99+
    2023-05-31
    android
  • Android中Activity过渡动画的实例讲解
    目录前言分解动画效果视频解析滑动动画效果视频解析淡出动画效果视频解析共享元素共享单个元素解析共享多个元素效果视频全部代码总结前言 以前Activty之间得跳转非常生硬,自Androi...
    99+
    2022-11-12
  • CSS变形、过渡的实例分析
    这篇文章主要介绍“CSS变形、过渡的实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“CSS变形、过渡的实例分析”文章能帮助大家解决问题。   1、过渡tra...
    99+
    2022-10-19
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作