vue3-内置组件-Transition

news2024/11/18 21:52:55

基于状态变化的过渡和动画(常用)

建议多看几遍~~。然后动手去写写,学编程只有多动手才能有感觉。

内置组件:

它在任意别的组件中都可以被使用,无需注册。

Vue 提供了两个内置组件,可以帮助你制作基于状态变化的过渡和动画:

<Transition> 会在一个元素或组件进入和离开 DOM 时应用动画。本章节会介绍如何使用它。

<TransitionGroup> 会在一个 v-for 列表中的元素或组件被插入,移动,或移除时应用动画

Transition

进入或者离开的动画

  • 由 v-if 所触发的切换

  • 由 v-show 所触发的切换

  • 由特殊元素 <component> 切换的动态组件

  • 改变特殊的 key 属性

<script lang="ts" setup>
import { ref } from 'vue'

const show = ref(true)
</script>

<template>
  <div class="container">
    <button @click="show = !show">点击切换按钮状态</button>
    <Transition>
      <p v-if="show">hello</p>
    </Transition>
  </div>
</template>

<style lang="scss" scoped>
.container {
  /* 下面我们会解释这些 class 是做什么的 */
  .v-enter-active,
  .v-leave-active {
    transition: opacity 0.5s ease;
  }

  .v-enter-from,
  .v-leave-to {
    opacity: 0;
  }
}
</style>


<Transition> 仅支持单个元素或组件作为其插槽内容。如果内容是一个组件,这个组件必须仅有一个根元素。

当一个 <Transition> 组件中的元素被插入或移除时,会发生下面这些事情:

Vue 会自动检测目标元素是否应用了 CSS 过渡或动画。如果是,则一些 CSS 过渡 class 会在适当的时机被添加和移除。

如果有作为监听器的 JavaScript 钩子,这些钩子函数会在适当时机被调用。

如果没有探测到 CSS 过渡或动画、也没有提供 JavaScript 钩子,那么 DOM 的插入、删除操作将在浏览器的下一个动画帧后执行。

基于 CSS 的过渡效果

v-enter-from:进入动画的起始状态。在元素插入之前添加,在元素插入完成后的下一帧移除。

v-enter-active:进入动画的生效状态。应用于整个进入动画阶段。在元素被插入之前添加,在过渡或动画完成之后移除。这个 class 可以被用来定义进入动画的持续时间、延迟与速度曲线类型。

v-enter-to:进入动画的结束状态。在元素插入完成后的下一帧被添加 (也就是 v-enter-from 被移除的同时),在过渡或动画完成之后移除。

v-leave-from:离开动画的起始状态。在离开过渡效果被触发时立即添加,在一帧后被移除。

v-leave-active:离开动画的生效状态。应用于整个离开动画阶段。在离开过渡效果被触发时立即添加,在过渡或动画完成之后移除。这个 class 可以被用来定义离开动画的持续时间、延迟与速度曲线类型。

v-leave-to:离开动画的结束状态。在一个离开动画被触发后的下一帧被添加 (也就是 v-leave-from 被移除的同时),在过渡或动画完成之后移除。

v-enter-active 和 v-leave-active 给我们提供了为进入和离开动画指定不同速度曲线的能力,我们将在下面的小节中看到一个示例。

为过渡效果命名

我们可以给 Transition 组件传一个 name prop 来声明一个过渡效果名:

<Transition name="fade">
  ...
</Transition>

对于一个有名字的过渡效果,对它起作用的过渡 class 会以其名字而不是 v 作为前缀。比如,上方例子中被应用的 class 将会是 fade-enter-active 而不是 v-enter-active。这个“fade”过渡的 class 应该是这样:

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
CSS 的 transition
  1. Transition 一般都会搭配原生 CSS 过渡一起使用,正如你在上面的例子中所看到的那样。

  2. 这个 transition CSS 属性是一个简写形式,使我们可以一次定义一个过渡的各个方面,包括需要执行动画的属性、持续时间和速度曲线。

使用不同的持续时间和速度曲线来过渡多个属性示例:

<script lang="ts" setup>
import { ref } from 'vue'
const show = ref(true)
</script>

<template>
  <div class="container">
    <button @click="show = !show">点击切换按钮状态</button>
    <Transition name="slide-fade">
      <p v-if="show">持续时间和速度曲线控制</p>
    </Transition>
  </div>
</template>

<style lang="scss" scoped>
.container {
  /*
  进入和离开动画可以使用不同
  持续时间和速度曲线。
*/
  .slide-fade-enter-active {
    transition: all 0.3s ease-out;
  }

  .slide-fade-leave-active {
    transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
  }

  .slide-fade-enter-from,
  .slide-fade-leave-to {
    transform: translateX(20px);
    opacity: 0;
  }
}
</style>

CSS 的 animation

原生 CSS 动画和 CSS transition 的应用方式基本上是相同的,只有一点不同,那就是 *-enter-from 不是在元素插入后立即移除,而是在一个 animationend 事件触发时被移除。

对于大多数的 CSS 动画,我们可以简单地在 _-enter-active 和 _-leave-active class 下声明它们。下面是一个示例:

<script lang="ts" setup>
import { ref } from 'vue'
const show = ref(true)
</script>

<template>
  <div class="container">
    <button @click="show = !show">点击切换状态</button>
    <Transition name="bounce">
      <p v-if="show" style="text-align: center">这是 CSS transition 示例</p>
    </Transition>
  </div>
</template>

<style lang="scss" scoped>
.container {
  text-align: center;
  .bounce-enter-active {
    animation: bounce-in 0.5s;
  }
  .bounce-leave-active {
    animation: bounce-in 0.5s reverse;
  }
  @keyframes bounce-in {
    0% {
      transform: scale(0);
    }
    50% {
      transform: scale(1.25);
    }
    100% {
      transform: scale(1);
    }
  }
}
</style>


自定义过渡 class

你也可以向 <Transition> 传递以下的 props 来指定自定义的过渡 class:

  • enter-from-class

  • enter-active-class

  • enter-to-class

  • leave-from-class

  • leave-active-class

  • leave-to-class 你传入的这些 class 会覆盖相应阶段的默认 class 名。这个功能在你想要在 Vue 的动画机制下集成其他的第三方 CSS 动画库时非常有用,比如 Animate.css:

安装 animate.css 动画库,(已安装的可以忽略)

pnpm install animate.css --save
<!-- 假设你已经在页面中引入了 Animate.css -->
<script lang="ts" setup>
import { ref } from 'vue'
import 'animate.css'
const show = ref(true)
</script>

<template>
  <div class="container">
    <button @click="show = !show">点击切换状态</button>
    <Transition
      name="custom-classes"
      enter-active-class="animate__animated animate__zoomIn "
      leave-active-class="animate__animated animate__zoomOut"
    >
      <p v-if="show">引入animate动画库</p>
    </Transition>
  </div>
</template>

<style lang="scss" scoped>
.container {
  text-align: center;
}
</style>

同时使用 transition 和 animation

Vue 需要附加事件监听器,以便知道过渡何时结束。可以是 transitionend 或 animationend,这取决于你所应用的 CSS 规则。如果你仅仅使用二者的其中之一,Vue 可以自动探测到正确的类型。

然而在某些场景中,你或许想要在同一个元素上同时使用它们两个。举例来说,Vue 触发了一个 CSS 动画,同时鼠标悬停触发另一个 CSS 过渡。此时你需要显式地传入 type prop 来声明,告诉 Vue 需要关心哪种类型,传入的值是 animation 或 transition:

伪代码:

<Transition type="animation">...</Transition>
深层级过渡与显式过渡时长

尽管过渡 class 仅能应用在 <Transition> 的直接子元素上,我们还是可以使用深层级的 CSS 选择器,在深层级的元素上触发过渡效果。

<Transition name="nested">
  <div v-if="show" class="outer">
    <div class="inner">
      Hello
    </div>
  </div>
</Transition>
/* 应用于嵌套元素的规则 */
.nested-enter-active .inner,
.nested-leave-active .inner {
  transition: all 0.3s ease-in-out;
}

.nested-enter-from .inner,
.nested-leave-to .inner {
  transform: translateX(30px);
  opacity: 0;
}

/* ... 省略了其他必要的 CSS */

我们甚至可以在深层元素上添加一个过渡延迟,从而创建一个带渐进延迟的动画序列:

/* 延迟嵌套元素的进入以获得交错效果 */
.nested-enter-active .inner {
  transition-delay: 0.25s;
}

然而,这会带来一个小问题。默认情况下,<Transition> 组件会通过监听过渡根元素上的第一个 transitionend 或者 animationend 事件来尝试自动判断过渡何时结束。而在嵌套的过渡中,期望的行为应该是等待所有内部元素的过渡完成。

在这种情况下,你可以通过向 <Transition> 组件传入 duration prop 来显式指定过渡的持续时间 (以毫秒为单位)。总持续时间应该匹配延迟加上内部元素的过渡持续时间:

<Transition :duration="550">...</Transition>

如果有必要的话,你也可以用对象的形式传入,分开指定进入和离开所需的时间:

<Transition :duration="550">...</Transition>
性能考量

你可能注意到我们上面例子中展示的动画所用到的 CSS 属性大多是 transform 和 opacity 之类的。用这些属性制作动画非常高效,因为:

他们在动画过程中不会影响到 DOM 结构,因此不会每一帧都触发昂贵的 CSS 布局重新计算。

大多数的现代浏览器都可以在执行 transform 动画时利用 GPU 进行硬件加速。

相比之下,_像 height 或者 margin 这样的属性会触发 CSS 布局变动_,因此执行它们的动画效果更昂贵,需要谨慎使用。我们可以在 CSS-Triggers(https://csstriggers.com/) 这类的网站查询哪些属性会在执行动画时触发 CSS 布局变动。

JavaScript 钩子

你可以通过监听 <Transition> 组件事件的方式在过渡过程中挂上钩子函数:

<Transition
  @before-enter="onBeforeEnter"
  @enter="onEnter"
  @after-enter="onAfterEnter"
  @enter-cancelled="onEnterCancelled"
  @before-leave="onBeforeLeave"
  @leave="onLeave"
  @after-leave="onAfterLeave"
  @leave-cancelled="onLeaveCancelled"
>
  <!-- ... -->
</Transition>
// 在元素被插入到 DOM 之前被调用
// 用这个来设置元素的 "enter-from" 状态
function onBeforeEnter(el) {}

// 在元素被插入到 DOM 之后的下一帧被调用
// 用这个来开始进入动画
function onEnter(el, done) {
  // 调用回调函数 done 表示过渡结束
  // 如果与 CSS 结合使用,则这个回调是可选参数
  done()
}

// 当进入过渡完成时调用。
function onAfterEnter(el) {}

// 当进入过渡在完成之前被取消时调用
function onEnterCancelled(el) {}

// 在 leave 钩子之前调用
// 大多数时候,你应该只会用到 leave 钩子
function onBeforeLeave(el) {}

// 在离开过渡开始时调用
// 用这个来开始离开动画
function onLeave(el, done) {
  // 调用回调函数 done 表示过渡结束
  // 如果与 CSS 结合使用,则这个回调是可选参数
  done()
}

// 在离开过渡完成、
// 且元素已从 DOM 中移除时调用
function onAfterLeave(el) {}

// 仅在 v-show 过渡中可用
function onLeaveCancelled(el) {}

这些钩子可以与 CSS 过渡或动画结合使用,也可以单独使用。

在使用仅由 JavaScript 执行的动画时,最好是添加一个 :css="false" prop。这显式地向 Vue 表明可以跳过对 CSS 过渡的自动探测。除了性能稍好一些之外,还可以防止 CSS 规则意外地干扰过渡效果。

<Transition
  ...
  :css="false"
>
  ...
</Transition>

在有了 :css="false" 后,我们就自己全权负责控制什么时候过渡结束了。这种情况下对于 @enter 和 @leave 钩子来说,回调函数 done 就是必须的。否则,钩子将被同步调用,过渡将立即完成。

这里是使用 GreenSock 库(https://gsap.com/)执行动画的一个示例,你也可以使用任何你想要的库,比如 Anime.js (https://animejs.com/) 或者 Motion One(https://motion.dev/)。

可复用过渡效果

得益于 Vue 的组件系统,过渡效果是可以被封装复用的。要创建一个可被复用的过渡,我们需要为 <Transition> 组件创建一个包装组件,并向内传入插槽内容:

<!-- MyTransition.vue -->
<script>
// JavaScript 钩子逻辑...
</script>

<template>
  <!-- 包装内置的 Transition 组件 -->
  <Transition
    name="my-transition"
    @enter="onEnter"
    @leave="onLeave">
    <slot></slot> <!-- 向内传递插槽内容 -->
  </Transition>
</template>

<style>
/*
  必要的 CSS...
  注意:避免在这里使用 <style scoped>
  因为那不会应用到插槽内容上
*/
</style>

现在 MyTransition 可以在导入后像内置组件那样使用了:

<MyTransition>
  <div v-if="show">Hello</div>
</MyTransition>

出现时过渡

如果你想在某个节点初次渲染时应用一个过渡效果,你可以添加 appear prop:

<Transition appear>
  ...
</Transition>

元素间过渡

除了通过 v-if / v-show 切换一个元素,我们也可以通过 v-if / v-else / v-else-if 在几个组件间进行切换,只要确保任一时刻只会有一个元素被渲染即可:

<Transition>
  <button v-if="docState === 'saved'">Edit</button>
  <button v-else-if="docState === 'edited'">Save</button>
  <button v-else-if="docState === 'editing'">Cancel</button>
</Transition>
``

过渡模式

在之前的例子中,进入和离开的元素都是在同时开始动画的,因此我们不得不将它们设为 position: absolute 以避免二者同时存在时出现的布局问题。

然而,很多情况下这可能并不符合需求。我们可能想要先执行离开动画,然后在其完成之后再执行元素的进入动画。手动编排这样的动画是非常复杂的,好在我们可以通过向 <Transition> 传入一个 mode prop 来实现这个行为:

<Transition mode="out-in">
  ...
</Transition>

将之前的例子改为 mode="out-in" 后是这样:

<Transition> 也支持 mode="in-out",虽然这并不常用。

组件间过渡

<Transition> 也可以作用于动态组件之间的切换:

<Transition name="fade" mode="out-in">
  <component :is="activeComponent"></component>
</Transition>

动态过渡

<Transition> 的 props (比如 name) 也可以是动态的!这让我们可以根据状态变化动态地应用不同类型的过渡:

<Transition :name="transitionName">
  <!-- ... -->
</Transition>

这个特性的用处是可以提前定义好多组 CSS 过渡或动画的 class,然后在它们之间动态切换。

你也可以根据你的组件的当前状态在 JavaScript 过渡钩子中应用不同的行为。最后,创建动态过渡的终极方式还是创建可复用的过渡组件,并让这些组件根据动态的 props 来改变过渡的效果。掌握了这些技巧后,就真的只有你想不到,没有做不到的了。


欢迎关注,后面会有一些资源可以免费获取哟~

分享前后端编程经验,技术干货,技术方案,好用的开发工具和应用软件,人生经验感悟等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1435153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jmeter 01 -概述线程组

1、Jmeter:概述 1.1 是什么&#xff1f; Jmeter是Apache公司使用Java 开发的一款测试工具 1.2 为什么&#xff1f; 高效、功能强大 模拟一些高并发或多次循环等特殊场景 1.3 怎么用&#xff1f; 下载安装 1、下载jmeter&#xff0c;解压缩2、安装Java环境&#xff08;jmet…

【保姆级教程|YOLOv8改进】【5】精度与速度双提升,使用FasterNet替换主干网络

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

为什么(如何)从 Java 8/11 迁移到 Java 21,从 Spring Boot 2 迁移到最新的 Spring Boot 3.2 ?

介绍 如果您的工作配置与 Java 有一定的关系&#xff0c;您一定已经注意到 了Java 最新稳定版本 Java 21 引起了很多关注。 这个新版本引入了一些未来的功能&#xff0c;改进了之前引入/孵化的一些突破性功能&#xff0c;弃用了多余的功能&#xff0c;并删除了一些错误。它使…

Halcon 缺陷检测

文章目录 开闭运算&#xff0c;腐蚀膨胀的亮点问题灰度图像的开闭运算&#xff0c;腐蚀膨胀的亮点问题算子二值化算子 Halcon blob特征处理的方法检测缺陷Halcon Blob特征差分的方法检测缺陷Halcon 极坐标变换&#xff08;环形先转换坐标&#xff09;blob特征Halcon Blob局部二…

PySpark(四)PySpark SQL、Catalyst优化器、Spark SQL的执行流程

目录 PySpark SQL 基础 SparkSession对象 DataFrame入门 DataFrame构建 DataFrame代码风格 DSL SQL SparkSQL Shuffle 分区数目 DataFrame数据写出 Spark UDF Catalyst优化器 Spark SQL的执行流程 PySpark SQL 基础 PySpark SQL与Hive的异同 Hive和Spark 均是:“分…

2月5日作业

1.请编程实现哈希表的创建存储数组(12,24,234,234,23,234,23),输入key查找的值&#xff0c;实现查找功能 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> typedef int datatype; typedef struct node {datatype data;str…

JenkinsGitLab完成自动化构建部署

关于GitLab安装:GitLab安装-CSDN博客 Docker中安装GitLab:Docker下安装GitLab-CSDN博客 安装JenKins Jenkins官网:Jenkins 中文版:Jenkins 安装时候中文页面的war包下不来 在英文页面 记得装JDK8以上 JenKins使用java写的 运行JenKins需要JDK环境 我这里已经装好了 将下…

VXLAN:虚拟化网络的强大引擎

1.什么是VXLAN VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff0c;虚拟扩展局域网&#xff09;&#xff0c;是由IETF定义的NVO3&#xff08;Network Virtualization over Layer 3&#xff09;标准技术之一&#xff0c;是对传统VLAN协议的一种扩展。VXLAN的特…

华为云GaussDB在新零售云转型上的摸索实验

新零售的“云化” 阿里研究院曾经提到过一个理念&#xff1a; 零售的本质是无时无刻不为消费者提供超出预期的“内容”。 这个理念其实不难理解&#xff0c;想要留住消费者&#xff0c;靠大家都能提供的“内容”显然是行不通的。超出预期&#xff0c;才能吸引消费者的“消费…

5-4、S加减单片机程序【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本节介绍实现步进电机S曲线运动的代码 一、目标功能 实现步进电机转动总角度720&#xff0c;其中加减速各90 加速段&#xff1a;加速类型&#xff1a;S曲线  加速角度&#xff1a;角度为90  起步速度…

Python:批量url链接保存为PDF

我的数据是先把url链接获取到存入excel中&#xff0c;后续对excel做的处理&#xff0c;各位也可以直接在程序中做处理&#xff0c;下面就是针对excel中的链接做批量处理 excel内容格式如下&#xff08;涉及具体数据做了隐藏&#xff09; 标题文件链接文件日期网页标题1http://…

标准库 STM32+EC11编码器+I2C ssd1306多级菜单例程

标准库 STM32EC11编码器I2C ssd1306多级菜单例程 &#x1f4cc;原创项目来源于&#xff1a;https://github.com/AdamLoong/Embedded_Menu_Simple&#x1f4cd;相关功能演示观看&#xff1a;https://space.bilibili.com/74495335 单片机多级菜单v1.2 &#x1f449;本次采用的是原…

对于模糊查询的SQL,怎么优先返回等值记录

说明&#xff1a;记录一次SQL改进的方法&#xff0c;希望能对大家有启发。 场景 前端项目有一个输入框&#xff0c;根据输入的银行名称&#xff0c;去模糊查询对应的数据库表&#xff0c;返回结果集&#xff0c;显示到下拉列表中。 因为银行名称字段包括了分行名&#xff0c…

【机器学习】机器学习简单入门

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;matplotlib &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

Linux基础-磁盘

1.磁盘分区 1.分区有固定大小 2.直接写在这块盘的磁盘分区表中&#xff08;DPT&#xff09;&#xff0c;和上面装什么操作系统没有任何关系 2.每一个磁盘分区都要先有一个磁盘分区类型 GPT&#xff08;首选&#xff09; MBR 3.磁盘专业术语叫做块设备&#xff08;Block Dev…

re:从0开始的CSS学习之路 2. 选择器超长大合集

0. 写在前面 虽然现在还是不到25的青年人&#xff0c;有时仍会感到恐慌&#xff0c;害怕不定的未来&#xff0c;后悔失去的时间&#xff0c;但细细想来&#xff0c;只有自己才知道&#xff0c;再来一次也不会有太多的改变。 CSS的选择器五花八门&#xff0c;而且以后在JavaScr…

【DDD】学习笔记-数据模型与对象模型

在建立数据设计模型时&#xff0c;我们需要注意表设计与类设计之间的差别&#xff0c;这事实上是数据模型与对象模型之间的差别。 数据模型与对象模型 我们首先来分析在设计时对冗余的考虑。前面在讲解数据分析模型时就提及&#xff0c;在确定数据项模型时&#xff0c;需要遵…

Go语言每日一练——链表篇(五)

传送门 牛客面试笔试必刷101题 ----------------合并k个已排序的链表 题目以及解析 题目 解题代码及解析 解析 这一道题与昨天的合并链表题目类似&#xff0c;但是由于有K个且时间复杂度要求控制在O(nlogn)&#xff0c;这里主要有两种解法&#xff1a;一种是依旧使用归并来…

7.0 Zookeeper 客户端基础命令使用

zookeeper 命令用于在 zookeeper 服务上执行操作。 首先执行命令&#xff0c;打开新的 session 会话&#xff0c;进入终端。 $ sh zkCli.sh 下面开始讲解基本常用命令使用&#xff0c;其中 acl 权限内容在后面章节详细阐述。 ls 命令 ls 命令用于查看某个路径下目录列表。…

函数的连续与间断【高数笔记】

【连续】 分类&#xff0c;分几个&#xff1f;每类特点&#xff1f; 连续条件&#xff0c;是同时满足还是只需其一&#xff1f; 【间断】 分类&#xff0c;分几个大类&#xff0c;又分几个小类&#xff1f;每类特点&#xff1f; 间断条件&#xff0c;是同时满足还是只需其一&am…