Vue 入门到实战 五

5章 过渡与动画

目录

5.1 单元素/组件过渡

5.1.1 过渡class

5.1.2 CSS 过渡

5.1.3 CSS 动画

5.1.4 同时使用过渡和动画

5.1.5 JavaScript 钩子方法

5.2 多元素/组件过渡

5.2.1 多元素过渡

5.2.2 多组件过渡

5.3 列表过渡

5.3.1 列表的普通过渡

5.3.2 列表的平滑过渡

5.3.3 列表的变换过渡

5.3.4 多维列表的过渡


5.1 单元素/组件过渡

Vue在插入、更新或者移除 DOM 时,提供多种不同方式的过渡效果(一个淡入淡出的效果)。在条件渲染(使用v-if)、条件展示(使用v-show)、动态组件、组件根节点等情形中,可以给任何元素和组件添加进入/离开过渡。Vue提供了内置的过渡封装组件<transition>,该组件用于包裹要实现过渡效果的组件。具体语法如下:

<transition name = "过渡名称">

  <!--要实现过渡效果的组件-->

</transition>

5.1.1 过渡class

总结起来就分为 进入 和 离开 动画的 初始状态、生效状态、结束状态,具体如下:

  • 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 前缀是允许修改的,可以 <Transition> 组件传一个 name 的 prop 来声明一个过渡效果名,如下就是将 v 前缀修改为 modal 前缀:

<div id="app"><button @click="show = !show">点我,我就渐渐的离开、渐渐的来。</button><transition name="fade"><p v-show="show" :style="styleobj">动画实例</p></transition>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {show: true,styleobj: {fontSize: '30px',color: 'red'}}}})app.mount('#app')
</script>
<style>.fade-enter-active,.fade-leave-active {transition: opacity 2s ease;}.fade-enter-from,.fade-leave-to {opacity: 0;}
</style>

5.1.2 CSS 过渡

常用的过渡一般都是CSS过渡。CSS过渡,顾名思义也就是使用过渡class定义CSS实现过渡效果。

5-2】使用过渡class定义图片的进入和离开动画效果,运行效果如图5.2所示。

 

<div id="app"><button @click="show = !show">切换显示图片</button><transition name="slide-img"><p v-if="show"><img src="99.jpg"/></p></transition>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {show: true}}})app.mount('#app')
</script>
<style>.slide-img-enter-active {	    transition: all 5s ease-out; //ease-out 规定以慢速结束的过渡,进入界面需要延迟5秒才会显示整个图片}.slide-img-leave-active {transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);}.slide-img-enter-from,.slide-img-leave-to {  transform: rotateX(45deg);   //X轴45°旋转transform: rotateY(45deg);  transform: rotateZ(45deg);  transform: rotate3d(1, 1, 1, 45deg);opacity: 0;}
</style>

5.1.3 CSS 动画

CSS动画与CSS过渡用法相同,区别是在动画中v-enter类名在节点插入DOM后不会立即被删除,而是在animationend(动画结束)事件触发时删除。

1. 基本概念
CSS 动画由两个主要部分组成:

@keyframes:定义动画的关键帧,指定动画在不同时间点的状态。
     animation:应用于元素的属性,控制动画的播放、持续时间、延迟等。
2. @keyframes 关键帧的定义
@keyframes 定义了动画的各个关键帧,控制元素的从一个状态到另一个状态的转换过程。

5-3】使用@keyframes定义图片的动画规则,运行效果如图5.3所示。

<div id="app"><button @click="show = !show">切换图片动画</button><transition name="bounce-img"><p v-if="show"><img src="99.jpg" /></p></transition>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {show: true}}})app.mount('#app')
</script>
<style>.bounce-img-enter-active {animation: bounce-in 0.8s;}.bounce-img-leave-active {animation: bounce-in 0.8s reverse;}@keyframes bounce-in {0% {transform: scale(0);}50% {transform: scale(1.25);}100% {transform: scale(1);}}
</style>

 

5.1.4 同时使用过渡和动画

在一些应用场景中,需要给一个元素同时设置过渡和动画,比如 animation 很快的被触发并完成,而 transition 效果还没结束。这时,需要使用 type属性并设置 animation transition值来明确声明需要Vue监听的类型。

<transition> 组件的 duration prop上可显性定义过渡持续时间(以毫秒计),比如,定制进入和移出的持续时间:<transition :duration="{ enter:1000, leave: 2000 }">...</transition>。还可以通过appear属性设置DOM节点在初始渲染的过渡(页面加载的初次过渡动画):<transition appear>...</transition>

<head><!--使用第三方动画库--><link rel="stylesheet" type="text/css" href="https://cdn.bootcss.com/animate.css/3.7.2/animate.min.css">
</head>
<!--使用type='transition'以transition过渡时长为准,
即fade-enter-active和fade-leave-active定义的时长,
或者绑定属性:duration="{enter:5000,leave:5000}"自定义时长,
type='transition'与:duration="5000" 二选一;
使用animate.css必须使用vue的 enter-active-class 和 leave-active-class,
后面紧跟animated类名和想使用的动画名称;
appear,appear-active-class实现页面加载的初次动画(初始渲染过渡)。-->
<div id="app"><transition name='fade' appear :duration="{enter:5000,leave:5000}"enter-active-class='animated swing fade-enter-active' leave-active-class='animated shake fade-leave-active'appear-active-class='animated swing' ><div v-if='show'>hello world</div></transition><button @click="handleClick">切换显示</button>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {show: true}},methods: {handleClick() {this.show = !this.show}}})app.mount('#app')
</script>
<style type="text/css">.fade-enter,.fade-leave-to {opacity: 0;}.fade-enter-active,.fade-leave-active {transition: opacity 5s;}div {font-size: 40px;margin: 50px auto;}
</style>

5.1.5 JavaScript 钩子方法

 

<div id="app"><button @click="show = !show" class="btn">添加到购物车</button><transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter"><div v-if="show" class="ball"></div></transition>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {show: false}},methods: {//el表示将要执行动画的DOM元素,beforeEnter表示动画开始前beforeEnter(el) {//设置元素动画开始前的起始位置el.style.transform = "translate(0, 0)"},enter(el, done) {//返回元素的宽度,强制动画刷新el.offsetWidth//设置元素动画开始之后的样式,设置完成之后状态el.style.transform = "translate(200px, -200px)"el.style.transition = "all 3s cubic-bezier(0, 0.54, 0.55, 1.18)"//done这里代表afterEnter方法的引用done()},afterEnter(el) {//动画完成后,调用该方法this.show = !this.show}}})app.mount('#app')
</script>
<style>.ball {width: 30px;height: 30px;border-radius: 50%;background-color: green;position: absolute;z-index: 99;top: 200px;left: 100px;}.btn {position: absolute;top: 200px;}
</style>

5.2 多元素/组件过渡

5.2.1 多元素过渡

对于原生元素可以使用v-if/v-else实现多元素过渡。最常见的多元素过渡是一个列表和描述这个列表为空消息的元素:

<transition>

  <table v-if="items.length > 0">

  <!-- ... -->

  </table>

  <p v-else>没有列表内容</p>

</transition>

实际上,通过使用多个v-if或将单个元素绑定到一个动态属性上,可以在任意数量的元素之间进行过渡。

<div id="app"><button @click="handleClick('saved')">显示Edit</button>&nbsp;&nbsp;<button @click="handleClick('edited')">显示Save</button>&nbsp;&nbsp;<button @click="handleClick('editing')">显示Cancel</button><br><br><transition name="fade" mode="out-in"><!--这里使用key让vue区分相同标签名元素,触发过渡--><button :key="docState">{{ buttonMessage }}</button></transition>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {docState: ''}},methods: {handleClick(myVal) {this.docState = myVal}},computed: {buttonMessage() {switch (this.docState) {case 'saved': return 'Edit'case 'edited': return 'Save'case 'editing': return 'Cancel'default: return '初始按钮'}}}})app.mount('#app')
</script>
<style type="text/css">.fade-enter-from,.fade-leave-to {opacity: 0;}.fade-enter-active,.fade-leave-active {transition: opacity 5s ease;}
</style>

5.2.2 多组件过渡

可以使用多组件过渡将多个组件包装成动态组件的效果。

5-7】设计一个类似于选项卡的页面,单击“多组件过渡按钮”将 “登录子组件”和“注册子组件”进行切换。

<div id="app"><button @click="show">多组件过渡按钮</button><transition name="check" mode="out-in"><!-- is用来展示的template组件,mode组件切换的模式,name过渡的前缀,component占位符表示展示的组件 --><component :is="view"></component></transition>
</div>
<!-- 登录子组件 -->
<template id="login"><div><h1>登录子组件</h1></div>
</template>
<!-- 注册子组件 -->
<template id="register"><div><h1>注册子组件</h1></div>
</template>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {view: 'login'}},methods: {show: function () {if (this.view == "login") {this.view = "register"} else {this.view = "login"}}},components: {login: {template: "#login"},register: {template: "#register"}}})app.mount('#app')
</script>
<style type="text/css">.check-enter-from,.check-leave-to {opacity: 0;}.check-enter-active,.check-leave-active {transition: opacity 5s ease;}
</style>

5.3 列表过渡

对于列表元素,可使用<transition-group>组件进行过渡。<transition-group>组件具有以下几个特点:

1、不同于 <transition>组件,它默认以<span>元素渲染。

2、过渡模式不可用,因为不再相互切换特有的元素。

3、内部元素需要提供唯一的key属性值。

4CSS过渡类将会应用在组件内部的元素中,而不是组件本身。

5.3.1 列表的普通过渡

5.3.2 列表的平滑过渡

在例5-8中,当添加和移除元素时,周围元素将瞬间移动到它们的新布局位置,而不是平滑的过渡。

<transition-group> 组件不仅可以进入和离开列表过渡,还可以通过v-move特性改变定位,进行平滑过渡。v-move特性像之前的类名一样,可以通过name属性来自定义前缀。

<div id="list-demo" class="demo"><button @click="add">添加元素</button>&nbsp;<button @click="remove">移除元素</button><transition-group name="list" tag="p"><span v-for="item in items" :key="item" class="list-item">{{item}}</span></transition-group>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {items: [1, 2, 3, 4, 5, 6, 7, 8, 9],nextNum: 10}},methods: {randomIndex() {return Math.floor(Math.random() * this.items.length)},add() {this.items.splice(this.randomIndex(), 0, this.nextNum++)},remove() {this.items.splice(this.randomIndex(), 1)}}})app.mount('#list-demo')
</script>
<style>.list-item {display: inline-block;margin-right: 10px;}.list-enter-active,.list-leave-active {transition: all 3s;}.list-enter,.list-leave-to {opacity: 0;transform: translateY(30px);}
</style>

5-9】列表的平滑过渡,可以在例5-8的基础上,做出如下改进:1、增加.list-move样式,使元素在进入时实现过渡效果;2、在.list-leave-active中设置绝对定位,使元素在离开时实现过渡效果。

<div id="list-demo" class="demo"><button @click="add">添加元素</button>&nbsp;<button @click="remove">移除元素</button><transition-group name="list" tag="p"><span v-for="item in items" :key="item" class="list-item">{{item}}</span></transition-group>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {items: [1, 2, 3, 4, 5, 6, 7, 8, 9],nextNum: 10}},methods: {randomIndex() {return Math.floor(Math.random() * this.items.length)},add() {this.items.splice(this.randomIndex(), 0, this.nextNum++)},remove() {this.items.splice(this.randomIndex(), 1)}}})app.mount('#list-demo')
</script>
<style>.list-item {display: inline-block;margin-right: 10px;}.list-move,.list-enter-active,.list-leave-active {transition: 3s;}.list-leave-active {position: absolute;}.list-enter,.list-leave-to {opacity: 0;transform: translateY(30px);}
</style>

5.3.3 列表的变换过渡

利用move属性,进行变换过渡,即一个列表中的列表项既不增加也不减少,只是不断地变换其位置。

5-10】列表的变换过渡。

<div id="list-demo" class="demo"><button @click="shuffle">变换过渡</button><transition-group name="list" tag="ul"><li v-for="item in items" :key="item">{{item}}</li></transition-group>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {items: [1, 2, 3, 4, 5, 6, 7, 8, 9],nextNum: 10}},methods: {shuffle() {this.items = this.items.sort(() => { return Math.random() - 0.5; })}}})app.mount('#list-demo')
</script>
<style>.list-move {transition: transform 3s;}
</style>

5.3.4 多维列表的过渡

FLIP动画不仅可以实现单列表过渡,多维网格列表的过渡也同样简单。

5-11】多维网格列表的过渡。

<div id="list-demo" class="demo"><button @click="shuffle">多维列表变换</button><transition-group name="cell" tag="div" class="container"><span v-for="cell in cells" :key="cell.id" class="cell">{{ cell.number }}</span></transition-group>
</div>
<script src="js/vue.global.js"></script>
<script>const app = Vue.createApp({data() {return {cells: Array.apply(null, { length: 81 }).map(function (_, index) {return {id: index,number: index % 9 + 1}})}},methods: {shuffle() {this.cells = this.cells.sort(() => { return Math.random() - 0.5; })}}})app.mount('#list-demo')
</script>
<style>.container {width: 270px;margin-top: 10px;line-height: 30px;text-align: center;}.cell {display: inline-block;width: 30px;height: 30px;outline: 1px solid #aaa;}.cell-move {transition: 3s;}
</style>

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

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

相关文章

Apache SeaTunnel脚本升级及参数调优实战

最近作者针对实时数仓的Apache SeaTunnel同步链路&#xff0c;完成了双引擎架构升级与全链路参数深度调优&#xff0c;希望本文能够给大家有所启发&#xff0c;欢迎批评指正&#xff01; Apache SeaTunnel 版本 &#xff1a;2.3.9 Doris版本&#xff1a;2.0.6 MySQL JDBC Conne…

C++ 时间操作:获取有史以来的天数与文件计数器

C 时间操作&#xff1a;获取有史以来的天数与文件计数器 在C中&#xff0c;时间操作是一个非常重要的功能&#xff0c;尤其是在需要处理日期、时间戳或定时任务时。本文将介绍如何利用C的时间操作功能&#xff0c;实现以下两个目标&#xff1a; 获取从Unix纪元时间&#xff0…

Python Bug修复案例分析:Python 中常见的 IndentationError 错误 bug 的修复

在 Python 编程的世界里&#xff0c;代码的可读性和规范性至关重要。Python 通过强制使用缩进来表示代码块的层次结构&#xff0c;这一独特的设计理念使得代码更加清晰易读。然而&#xff0c;正是这种对缩进的严格要求&#xff0c;导致开发者在编写代码时&#xff0c;稍有不慎就…

【论文笔记】Transformer

Transformer 2017 年&#xff0c;谷歌团队提出 Transformer 结构&#xff0c;Transformer 首先应用在自然语言处理领域中的机器翻译任务上&#xff0c;Transformer 结构完全构建于注意力机制&#xff0c;完全丢弃递归和卷积的结构&#xff0c;这使得 Transformer 结构效率更高…

CI/CD(三) 安装nfs并指定k8s默认storageClass

一、NFS 服务端安装&#xff08;主节点 10.60.0.20&#xff09; 1. 安装 NFS 服务端 sudo apt update sudo apt install -y nfs-kernel-server 2. 创建共享目录并配置权限 sudo mkdir -p /data/k8s sudo chown nobody:nogroup /data/k8s # 允许匿名访问 sudo chmod 777 /dat…

【QA】单件模式在Qt中有哪些应用?

单例设计模式确保一个类仅有一个实例&#xff0c;并提供一个全局访问点来获取该实例。在 Qt 框架中&#xff0c;有不少类的设计采用了单例模式&#xff0c;以下为你详细介绍并给出相应代码示例。 1. QApplication QApplication 是 Qt GUI 应用程序的核心类&#xff0c;每个 Q…

存储过程触发器习题整理1

46、{blank}设有商品表(商品号&#xff0c;商品名&#xff0c;单价)和销售表(销售单据号&#xff0c;商品号&#xff0c;销售时间&#xff0c;销售数量&#xff0c;销售单价)。其中&#xff0c;商品号代表一类商品&#xff0c;商品号、单价、销售数量和销售单价均为整型。请编写…

基于ChatGPT、GIS与Python机器学习的地质灾害风险评估、易发性分析、信息化建库及灾后重建高级实践

第一章、ChatGPT、DeepSeek大语言模型提示词与地质灾害基础及平台介绍【基础实践篇】 1、什么是大模型&#xff1f; 大模型&#xff08;Large Language Model, LLM&#xff09;是一种基于深度学习技术的大规模自然语言处理模型。 代表性大模型&#xff1a;GPT-4、BERT、T5、Ch…

单表达式倒计时工具:datetime的极度优雅(智普清言)

一个简单表达式&#xff0c;也可以优雅自成工具。 笔记模板由python脚本于2025-03-22 20:25:49创建&#xff0c;本篇笔记适合任意喜欢学习的coder翻阅。 【学习的细节是欢悦的历程】 博客的核心价值&#xff1a;在于输出思考与经验&#xff0c;而不仅仅是知识的简单复述。 Pyth…

最优编码树的双子性

现在看一些书&#xff0c;不太愿意在书上面做一些标记&#xff0c;也没啥特殊的原因。。哈哈。 树的定义 无环连通图&#xff0c;极小连通图&#xff0c;极大无环图。 度 某个节点&#xff0c;描述它的度&#xff0c;一般默认是出度&#xff0c;分叉的边的条数。或者说孩子…

MiB和MB

本文来自腾讯元宝 MiB 和 ​MB 有区别&#xff0c;尽管它们都用于表示数据存储的单位&#xff0c;但它们的计算方式不同&#xff0c;分别基于不同的进制系统。 1. ​MiB&#xff08;Mebibyte&#xff09;​ ​MiB 是基于二进制的单位&#xff0c;使用1024作为基数。1 MiB 102…

Labview和C#调用KNX API 相关东西

叙述:完全没有听说过KNX这个协议...................我这次项目中也是简单的用了一下没有过多的去研究 C#调用示例工程链接(labview调用示例在 DEBUG文件夹里面) 通过网盘分享的文件&#xff1a;KNX调用示例.zip 链接: https://pan.baidu.com/s/1NQUEYM11HID0M4ksetrTyg?pwd…

损失函数理解(二)——交叉熵损失

损失函数的目的是为了定量描述不同模型&#xff08;例如神经网络模型和人脑模型&#xff09;的差异。 交叉熵&#xff0c;顾名思义&#xff0c;与熵有关&#xff0c;先把模型换成熵这么一个数值&#xff0c;然后用这个数值比较不同模型之间的差异。 为什么要做这一步转换&…

Kubernetes的Replica Set和ReplicaController有什么区别

ReplicaSet 和 ReplicationController 是 Kubernetes 中用于管理应用程序副本的两种资源&#xff0c;它们有类似的功能&#xff0c;但 ReplicaSet 是 ReplicationController 的增强版本。 以下是它们的主要区别&#xff1a; 1. 功能的演进 ReplicationController 是 Kubernete…

信息系统运行管理员教程3--信息系统设施运维

第3章 信息系统设施运维 信息系统设施是支撑信息系统业务活动的信息系统软硬件资产及环境。 第1节 信息系统设施运维的管理体系 信息系统设施运维的范围包含信息系统涉及的所有设备及环境&#xff0c;主要包括基础环境、硬件设备、网络设备、基础软件等。 信息系统设施运维…

如何通过Python实现自动化任务:从入门到实践

在当今快节奏的数字化时代,自动化技术正逐渐成为提高工作效率的利器。无论是处理重复性任务,还是管理复杂的工作流程,自动化都能为我们节省大量时间和精力。本文将以Python为例,带你从零开始学习如何实现自动化任务,并通过一个实际案例展示其强大功能。 一、为什么选择Pyt…

Spring Boot 与 MyBatis Plus 整合 KWDB 实现 JDBC 数据访问

​ 引言 本文主要介绍如何在 IDEA 中搭建一个使用 Maven 管理的 Spring Boot 应用项目工程&#xff0c;并结合在本地搭建的 KWDB 数据库&#xff08;版本为&#xff1a;2.0.3&#xff09;来演示 Spring Boot 与 MyBatis Plus 的集成&#xff0c;以及对 KWDB 数据库的数据操作…

Java锁等待唤醒机制

在 Java 并发编程中&#xff0c;锁的等待和唤醒机制至关重要&#xff0c;通常使用 wait()、notify() 和 notifyAll() 来实现线程间的协调。本文将详细介绍这些方法的用法&#xff0c;并通过示例代码加以说明。 1. wait()、notify() 与 notifyAll() 在 Java 中&#xff0c;Obj…

 UNIX网络编程笔记:TCP客户/服务器程序示例

服务器实例 有个著名的项目&#xff0c;tiny web&#xff0c;本项目将其改到windows下&#xff0c;并使用RAII重构&#xff0c;编写过程中对于内存泄漏确实很头疼&#xff0c;还没写完&#xff0c;后面会继续更&#xff1a; #include <iostream> #include <vector&g…

AI Agent开发大全第四课-提示语工程:从简单命令到AI对话的“魔法”公式

什么是提示语工程&#xff1f;一个让AI“听话”的秘密 如果你曾经尝试过用ChatGPT或者其他大语言模型完成任务&#xff0c;那么你一定遇到过这样的情况&#xff1a;明明你的问题是清晰的&#xff0c;但答案却离题万里&#xff1b;或者你认为自己提供的信息足够详尽&#xff0c…