Vue 2 进入、离开和列表过渡

2023-09-14 16:06:12

前言

Vue 提供了多种方式来实现过渡效果。

  1. 在 CSS 过渡和动画中自动应用 class
  2. 配合 CSS 动画库
  3. 过渡钩子函数中使用 JavaScript 操作 DOM
  4. 配合 JavaScript 动画库

单元素/组件的过渡

将元素或组件放在 <transition> 中可以在下列情形中触发过渡效果:

  1. 使用了 v-if
  2. 使用了 v-show
  3. 使用了动态组件
  4. 组件根节点

如果没有找到 JavaScript 过渡钩子和 CSS 过渡/动画,DOM 操作在下一帧中立即执行。


过渡的类名

Vue提供了 6 个可以自动生成的 CSS 类名,如下图。

可以自动生成的类名是指给 transition 组件的 name 属性指定一个值,假设是 fade,那么该 name 将自动扩展生成 .fade-enter、.fade-enter-active、.fade-enter-to等上述6个类,并应用在 transition 组件里的过渡元素或组件上。

示例:

<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <style>
        .fade-enter {
            opacity: 0;
            transform: translateY(-20px);
        }

        .fade-enter-active {
            transition: all 0.3s ease;
        }

        .fade-enter-to {
            opacity: 1;
            transform: translateY(0);
        }

        .fade-leave {
            opacity: 1;
        }

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

        .fade-leave-to {
            opacity: 0;
        }
    </style>
</head>

<body>
    <div id="app">
        <button @click="showElement=!showElement">显示/隐藏元素</button>
        <transition name="fade">
            <div v-if="showElement">
                你好
            </div>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                showElement: false
            },
        });
    </script>
</body>

</html>

在这里插入图片描述


自定义过渡类名

如果想结合使用 animate.css 动画库,可以在 transition 组件使用以下 props 来指定类名:

  • enter-class
  • enter-active-class
  • enter-to-class
  • leave-class
  • leave-active-class
  • leave-to-class

示例:

<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
</head>

<body>
    <div id="app">
        <button @click="showElement=!showElement">显示/隐藏元素</button>
        <transition
            enter-active-class="animated fadeInLeft"
            leave-active-class="animated fadeOut">
            <div v-if="showElement">
                你好
            </div>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                showElement: false
            },
        });
    </script>
</body>

</html>

在这里插入图片描述

Animate 动画演示


指定要监听的事件类型

通过设置 transition 组件的 type 属性来指定要监听的过渡事件类型(transitionend 和 animationend)。

type 值可以是 transition 或 animation。

示例:

<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <style>
        .fade-enter {
            opacity: 0;
            transform: translateY(-20px);
        }
    
        .fade-enter-active {
            transition: all 0.3s ease;
        }
    
        .fade-enter-to {
            opacity: 1;
            transform: translateY(0);
        }
    
        .fade-leave {
            opacity: 1;
        }
    
        .fade-leave-active {
            transition: opacity 0.5s ease;
        }
    
        .fade-leave-to {
            opacity: 0;
        }
    </style>
</head>

<body>
    <div id="app">
        <button @click="toggleElement">Toggle Element</button>
        <transition name="fade"
            type="transition"
            >
            <div v-if="showElement" key="element">Hello, Vue!</div>
        </transition>
        <transition name="bounce"
            enter-active-class="animated bounceIn"
            leave-active-class="animated bounceOut"
            type="animation"
            >
            <div v-if="showElement" key="element">Hello, vue!</div>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                showElement: false
            },
            methods: {
                toggleElement() {
                    this.showElement = !this.showElement;
                },
            },
        });
    </script>
</body>

</html>

在这里插入图片描述


指定过渡持续时间

默认情况下,Vue 会等待过渡所在根元素的第一个 transitionend 或 animationend 事件。

我们可以使用 transition 组件上的 duration prop 定制一个显示的过渡持续时间,以毫秒为单位。

<transition :duration="1000">...</transition>

<transition :duration="{ enter: 500, leave: 800 }">...</transition>

transition 组件上的 JavaScript 钩子函数

共 8 个:

  • before-enter
  • enter
  • after-enter
  • enter-cancelled
  • before-leave
  • leave
  • after-leave
  • leave-cancelled

注意点:

  • 只用 JavaScript 过渡时,在 leave 和 enter 中必须使用 done 参数来告诉 Vue何时过渡已经完成。
  • 推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <!--
        Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择
    -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
    </style>
</head>

<body>
    <div id="app">
        <button @click="toggleElement">切换元素</button>
        <transition name="custom-transition" @before-enter="beforeEnter" @enter="enter" @leave="leave">
            <div v-if="showElement" key="element">Hello, Vue!</div>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                showElement: false
            },
            methods: {
                toggleElement() {
                    this.showElement = !this.showElement;
                },
                beforeEnter(el) {
                    // 在进入过渡开始之前调用
                    el.style.opacity = 0;
                },
                enter(el, done) {
                    // 在进入过渡的主要阶段调用
                    Velocity(el, { opacity: 1, translateY: '0px',fontSize: '2em' }, { duration: 1000, complete: done });
                    Velocity(el, { fontSize: '1em' }, { complete: done })
                },
                leave(el, done) {
                    // 在离开过渡的主要阶段调用
                    Velocity(el, { opacity: 0, translateY: '20px' }, { duration: 1000, complete: done });
                },
            }
        });
    </script>
</body>

</html>

在这里插入图片描述


初始渲染的过渡

启用初始渲染的过渡:

<transition
	appear
	appear-class=""
	appear-active-class=""
	appear-to-class=""
	v-on:before-appear=""  
	v-on:appear=""  
	v-on:after-appear=""  
	v-on:appear-cancelled=""
	>
</transition>

多个元素的过渡

如果想实现多个原生元素的切换过渡,可以使用条件渲染的相关指令。

如果切换的元素标签名相同,比如都是 button ,那么最好给它们设置唯一的key属性,否则可能出现过渡效果不生效或没按设置过渡的情况。

<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <!--
        Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择
    -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
    </style>
</head>

<body>
    <div id="app">
        <button @click="toggleElement">切换元素</button>
        <transition @before-enter="beforeEnter" @enter="enter" @leave="leave">
            <div v-if="showElement" key="el1">Hello, girls!</div>
            <div v-else key="el2">Hello, boys!</div>
        </transition>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                showElement: false
            },
            methods: {
                toggleElement() {
                    this.showElement = !this.showElement;
                },
                beforeEnter(el) {
                    // 在进入过渡开始之前调用
                    el.style.opacity = 0;
                },
                enter(el, done) {
                    // 在进入过渡的主要阶段调用
                    Velocity(el, { opacity: 1, translateY: '0px',fontSize: '2em' }, { duration: 1000, complete: done });
                    Velocity(el, { fontSize: '1em' }, { complete: done })
                },
                leave(el, done) {
                    // 在离开过渡的主要阶段调用
                    Velocity(el, { opacity: 0, translateY: '20px' }, { duration: 1000, complete: done });
                },
            }
        });
    </script>
</body>

</html>

在这里插入图片描述

也可以使用绑定动态 property 的方式来替代使用了多个 v-if 的相同标签名元素

<transition>
	<div v-if="show==='el1'" key="el1">el1</div>
	<div v-if="show==='el2'" key="el2">el2</div>
</transition>

替换成

<transition>
	<div :key="el">el</div>
</transition>

过渡模式

在这里插入图片描述

如上图中,前一个元素的过渡结束时,另一个元素的过渡开始,这有时候并不是我们想要的效果。

于是,Vue 提供了过渡模式。

<transition name="fade" mode="out-in">
</transition>

mode 可以为以下值:

  • in-out:新元素先过渡进入,旧元素后过渡离开。
    在这里插入图片描述
  • out-in:旧元素先过渡离开,新元素再过渡进入。
    在这里插入图片描述

So cool!


多个组件的过渡

多个元素我们可以使用 key attribute,对于多个组件,我们可以使用更为简单的 is attribute,即动态组件。

<transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>

列表过渡

前面所讲都是针对单个节点或者多个节点中的一个。

而对于有多个节点的列表的渲染,我们使用 transition-group 组件。

transition-group 组件的特点:

  1. transition 不同,它以一个真实的元素存在,默认为 span,可以使用 tag attribute 修改。
  2. 不能使用过渡模式。
  3. 列表元素都需要 key attribute。
  4. CSS 过渡的类会自动应用在列表内部元素。

列表的进入/离开过渡

<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <!--
        Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择
    -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
    </style>
    <style>
        .list-enter-active,
        .list-leave-active {
            transition: opacity,transform 0.5s;
        }

        .list-enter,
        .list-leave-to {
            opacity: 0;
            transform: translateX(60px);
        }

        .list-item {
            list-style:decimal-leading-zero;
            margin: 5px;
            padding: 5px;
            background-color: #f0f0f0;
            border: 1px solid #ddd;
            border-radius: 5px;
            width: fit-content;
        }
    </style>
</head>

<body>
    <div id="app">
        <button @click="addItem">Add Item</button>
        <button @click="removeItem">Remove Item</button>
        <transition-group name="list" tag="ul">
            <li v-for="item in items" :key="item.id" class="list-item">
                {{item.text}}
            </li>
        </transition-group>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                items: [],
                nextItemId: 0
            },
            methods: {
                addItem() {
                    let randomIndex=Math.floor(Math.random()*this.items.length);
                    this.items.splice(randomIndex,0, {
                        id: this.nextItemId++,
                        text: `Item ${this.nextItemId}`
                    });
                },
                removeItem() {
                    let randomIndex = Math.floor(Math.random()*this.items.length);
                    this.items.splice(randomIndex, 1);
                }
            },
        });
    </script>
</body>

</html>

在这里插入图片描述


列表的排序过渡

不仅可以给进入/离开添加过渡,当列表的元素位置发生变化时,也可以产生过渡效果,通过 move-class attribute自定义类名来实现,也可以使用 name 作为前缀。

例如当 name="list" 时:

.list-move {
  transition: transform 1s;
}

这个可以解决列表过渡不够平滑的问题。

如果想给所有的变动都添加过渡动画,那么可以按以下方法做:

<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <!--
        Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择
    -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
    <style>
        .list-enter,
        .list-leave-to {
            opacity: 0;
            transform: translateX(30px);
        }

        .list-leave-active{
            position: absolute;
        }

        .list-item {
            transition: all 1s;
            list-style: none;
            margin: 5px;
            padding: 5px;
            background-color: #f0f0f0;
            border: 1px solid #ddd;
            border-radius: 5px;
            width: fit-content;
        }
    </style>
</head>

<body>
    <div id="app">
        <button @click="addItem">Add Item</button>
        <button @click="removeItem">Remove Item</button>
        <button @click="shuffleItems">Shuffle Items</button>
        <transition-group name="list" tag="ul">
            <li v-for="item in items" :key="item.id" class="list-item">
                {{item.text}}
            </li>
        </transition-group>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                items: [],
                nextItemId: 0
            },
            methods: {
                addItem() {
                    let randomIndex = Math.floor(Math.random() * this.items.length);
                    this.items.splice(randomIndex, 0, {
                        id: this.nextItemId++,
                        text: `Item ${this.nextItemId}`
                    });
                },
                removeItem() {
                    let randomIndex = Math.floor(Math.random() * this.items.length);
                    this.items.splice(randomIndex, 1);
                },
                shuffleItems() {
                    this.items = _.shuffle(this.items);
                }
            },
        });
    </script>
</body>

</html>

在这里插入图片描述

这被叫做  FLIP 过渡,使用这种过渡方式的元素不能设置为 display:inline


列表的交错过渡

通过 HTML 的 data 属性与 JavaScript 进行通信来实现交错排序。

<li  
v-for="(item, index) in computedList"  
v-bind:key="item.msg"  
v-bind:data-index="index"  
>{{ item.msg }}</li>
enter: function (el, done) {
  var delay = el.dataset.index * 150; // 通过 data-index 获取元素的索引,然后计算延迟时间
  setTimeout(function () {
    Velocity(
      el,
      { opacity: 1, height: '1.6em' }, // 使用 Velocity.js 库来应用 CSS 属性的动画效果
      { complete: done } // 动画完成后调用 done 回调函数来通知 Vue.js 过渡完成
    );
  }, delay);
},

每个元素都有不同的延迟,以实现交错的过渡效果。

在这里插入图片描述


可复用的过渡

使用 template :

Vue.component('my-special-transition', {
  template: '\
    <transition\
      name="reusable-transition"\
      mode="out-in"\
      v-on:before-enter="beforeEnter"\
      v-on:after-enter="afterEnter"\
    >\
      <slot></slot>\
    </transition>\
  ',
  methods: {
    beforeEnter: function (el) {
      // ...
    },
    afterEnter: function (el) {
      // ...
    }
  }
})

使用 函数式组件 :

Vue.component('reusable-transition', {
  functional: true,
  render: function (createElement, context) {
    var data = {
      props: {
        name: 'reusable-transition',
        mode: 'out-in'
      },
      on: {
        beforeEnter: function (el) {
          // ...
        },
        afterEnter: function (el) {
          // ...
        }
      }
    }
    return createElement('transition', data, context.children)
  }
})

使用 单文件组件:

<template>
  <transition name="fade">
    <slot></slot>
  </transition>
</template>

<script>
export default {
  name: 'ReusableTransition',
};
</script>

<style>
/* 在这里定义过渡的 CSS 类名和样式 */
.fade-enter-active, .fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active 在版本 2.1.8 中可用 */ {
  opacity: 0;
}
</style>

总之,可复用过渡就是以 transitiontransition-group 作为根元素。


动态过渡

我们可以根据组件的状态或属性动态地应用不同的过渡效果。

通常涉及使用过渡的不同名称、条件语句和组件的动态属性。

<!DOCTYPE html>
<html>

<head>
    <title>Vue 2 过渡 Demo</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    <!--
        Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择
    -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
    <style>
        .default-enter,
        .default-leave-to {
            opacity: 0;
            transform: translateX(30px);
        }

        .slide-enter,
        .slide-leave-to {
            transform: translateY(30px);
            opacity: 0;
        }

        .default-leave-active,
        .slide-leave-active{
            position: absolute;
        }

        .list-item {
            transition: all 1s;
        }
    </style>
</head>

<body>
    <div id="app">
        <input v-model="newTodo" @keyup.enter="addTodo" placeholder="添加新任务">
        <button @click="toggleTransition">切换过渡方式</button>
        <transition-group :name="dynamicTransitionName" tag="ul">
            <li v-for="todo in todos" :key="todo.id" class="list-item">
                {{todo.text}}
                <button @click="removeTodo(index)">删除</button>
            </li>
        </transition-group>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                dynamicTransitionName: 'default',
                newTodo: '',
                todos: [],
                nextID: 0
            },
            methods: {
                addTodo() {
                    if (this.newTodo.trim() !== '') {
                        this.todos.push({id:this.nextID++, text: this.newTodo });
                        this.newTodo = '';
                    }
                },
                removeTodo(index) {
                    this.todos.splice(index, 1);
                },
                toggleTransition(){
                    this.dynamicTransitionName=this.dynamicTransitionName==='default'?'slide':'default';
                }
            },
        });
    </script>
</body>

</html>

在这里插入图片描述

更多推荐

Haproxy集群调度器与部署

目录一、Haproxy介绍:1.Haproxy应用分析:2.Haproxy的特性:3.Haproxy常见的调度算法:4.LVS、Nginx、HAproxy的区别:4.1Haproxy与lvs对比:4.2Haproxy与nginx对比:5.Haproxy优点:二、Haproxy部署:1.配置Haproxy负载调度器:1.

【Spring】Spring的手动实现

🎄欢迎来到@边境矢梦°的csdn博文🎄🎄本文主要梳理手动实现Spring底层机制🎄🌈我是边境矢梦°,一个正在为秋招和算法竞赛做准备的学生🌈🎆喜欢的朋友可以关注一下🫰🫰🫰,下次更新不迷路🎆Ps:月亮越亮说明知识点越重要(重要性或者难度越大)🌑🌒🌓🌔🌕目录实现任务阶段1-编写自己Spring

Nginx rewrite+防盗链

NginxNginx6、重写功能rewrite6.1if指令6.2return6.3set指令6.4break指令6.5rewrite指令6.5.1基本原理6.5.2语法格式6.5.3举例6.5.3.1测试访问bj跳转到beijing6.5.3.2域名重定向:所有域名都跳转到accp7、防盗链7.1什么是防盗链7.2防

MySQL常用函数集锦 --- 字符串|数值|日期|流程函数总结

个人主页:兜里有颗棉花糖欢迎点赞👍收藏✨留言✉加关注💓本文由兜里有颗棉花糖原创收录于专栏【MySQL学习专栏】🎈本专栏旨在分享学习MySQL的一点学习心得,欢迎大家在评论区讨论💌目录一、字符串函数二、数值函数小练习三、日期函数四、流程函数一、字符串函数关于字符串函数请看此文章:字符串函数二、数值函数下面来介绍5

写一篇nginx配置指南

nginx.conf配置找到Nginx的安装目录下的nginx.conf文件,该文件负责Nginx的基础功能配置。配置文件概述Nginx的主配置文件(conf/nginx.conf)按以下结构组织:配置块功能描述全局块与Nginx运行相关的全局设置events块与网络连接有关的设置http块代理、缓存、日志、虚拟主机等

Golang 字符串

目录1.Golang字符串1.1.基础概念1.2.字符串编码1.3.遍历字符串1.4.类型转换1.5.总结1.6.StringConcatenation(字符串连接)1.6.1.Usingthe`+`operator1.6.2.Usingthe`+=`operator1.6.3.UsingtheJoinmethod1.

民安智库(第三方市场调查公司)开展景区游客满意度调查

为什么要开展景区游客满意度调查景区的经营管理是一个动态的过程,需要不定期的地进行调查,让管理者了解景区管理的不足之处,并不断地改善和提高管理水平,以保证经营目标的顺利完成。景区旅游要想真正地成为可持续发展的经济产业,就不能忽视游客的体验感受情况,这是因为旅游景区游客满意度的变化能直接反映出景区管理中存在的问题。现在国内

Twitter图片数据优化的细节

Twitter个人数据优化:吸引更多关注和互动头像照片在Twitter上,头像照片是最快识别一个账号的方法之一。因此,请务必使用公司的标志或与品牌相关的图片。建议尺寸为400x400像素。为了建立强大的品牌形象和一致性,强烈建议在所有社交媒体上使用相同的头像照片。您的Twitter简介是针对企业的160个字符的描述。它

数据分析与可视化项目技术参考

🙌秋名山码民的主页😂oi退役选手,Java、大数据、单片机、IoT均有所涉猎,热爱技术,技术无罪🎉欢迎关注🔎点赞👍收藏⭐️留言📝获取源码,添加WX目录1.考核的主要内容2.具体实现流程3.技术参考3.1数据获取3.2数据清洗与处理3.3数据存储到Mysql3.4网站开发3.4.1登录页面3.4.2数据可视化

数据库数据恢复-SQL SERVER数据库分区被格式化的数据恢复方案

SQLSERVER数据库故障类型:1、SQLSERVER数据库文件被删除。2、SQLSERVER数据库所在分区格式化。3、SQLSERVER数据库文件大小变为“0”。4、使用备份还原数据库时覆盖原数据库。SQLSERVER数据库故障原因:1、人为误操作。2、文件系统损坏,设备自动做磁盘检测。SQLSERVER数据库故障

【Spring Boot】Spring Boot源码解读与原理剖析

这里写目录标题前言精进SpringBoot首选读物“小册”变“大书”,彻底弄懂SpringBoot全方位配套资源,学不会来找我!技术新赛道,2023领先抢跑前言承载着作者的厚望,掘金爆火小册同名读物《SpringBoot源码解读与原理剖析》正式出书!本书前身是掘金社区销量TOP的小册——《SpringBoot源码解读与

热文推荐