【ANIMATIONS】使用动画和过渡

1,754 阅读6分钟

v-if/v-show会立即添加或者移除DOM元素,可以给变换的过程添加动画。

只能包含一个元素

包含多个个元素

不能用transition给由JavaScript添加的元素(比如使用appendChild添加的x新元素)加上动画

transition 配合v-if、v-show使用,只能是在模板里存在的元素

1.过渡的配置

添加css类

  • 添加

    添加类名

    • 出现 *-enter,Vue只在动画的第一帧添加它,是初始状态。
    • 设置过渡和最终的状态 *-enter-active 直到动画结束,它才被移除,动画持续的时常由vue决定,vue根据你在css代码内设置的时长来决定动画的时长,一旦元素就位,这个css类就会被移除。
  • 移除

    不输入名称,默认值是 v-enter

    • *-leave类
    • *-leave-active类
    //在transition元素上添加name属性,保证这些CSS类能被添加到vue元素上,vue就能嗅探这些CSS类。
    <transition name= "fade" type="animation">
        <div v-if="show">
            
        </div>
    </transition>
    
    <style>
    //淡入淡出 opacity默认值为1
    
    //只在动画最开始的第一帧添加它,初始状态
    .fade-enter{
    	opacity:0;
    }
    //过渡:在初始状态被移除时添加
    .fade-enter-active{
    	transition:opacity 1s;
    	//opacity:1;
    }
    .fade-leave{
    	//opacity:1;
    }
    .fade-leave-active{
    	transition:opacity 1s;
    	opacity:0;
    }
    </style>
    

    2.使用CSS动画属性来创建“滑动“过渡

    .slide-enter{
    
    }
    .slide-enter-active{
    	animation:slide-in 1s ease-out fowards;
    	transition:opacity 0.5s;
    }
    .slide-leave{
    
    }
    .slide-leave-active{
     	animation:slide-out 1s ease-out forwards;
     	transition:opacity 1s;
     	opacity:0;
    }
    @keyframes slide-in{
    	from{
    		transformY(20px);
    	}
    	to{
    		transformY(0)
    	}
    }
    @keyframes slide-out{
    	from{
    		transformY(0)
    	}
    	to{
    		transformY(20px);
    	}
    }
    

    3.混合过渡和动画两种形式

    animation transition两种形式可以混用,若两者持续时间不同的话,vue会选择较长的那一个。也可以自己进行定义,type="animation/transition"决定元素移除的时机,在动画或者过渡结束后就进行移除元素。

    4.v-if和v-show动画

    v-show工作原理,它没有删除或者添加任何元素,只是对display属性产生了影响。

    v-if更常用。

    5.配置初始化(加载)动画

    每次想要在这个页面开始加载时,都让这些元素有动画效果。 在这种情况下,所有元素都有流畅的过渡动画。通过一些效果,在用户打开这个页面是感觉自己来到了新的页面。

    使用appear属性,添加到transition组件上,vue在每次页面打开的时候,能在DOM元素上添加上初始动画。

    <transition name="fade" appear>
        
    </transition>
        
    

    6.使用不同的css类名

    Animate.css,是一个很好用的css动画库,能让大家很方便的使用这些动画,只需要简单的在元素上加一些css类即可。

    要使vue使用不同的样式的名称,而不是只是使用默认的样式名添加enter及 leave,需要添加额外的属性,可以覆盖掉vue自带的默认样式类。

    <transition
                
                enter-active-class="animated bounce"
               
                leave-class-active="animated shake">
    	
    </transition>
    

    通过自定义添加样式,告诉vue不要使用v-enter,v-enter-active,这种默认的样式类,也不要使用像*-enter-active这样的类,而让vue在特定的时间点,去使用某一特定的类,删掉值为空的属性,否则就会报错。在此种设置方式下,appear属性就会失效(它只会在当你使用默认动画时生效,也就是用默认的css类)。

    7.使用动态命名和属性

    <select v-model="alertAnimation">
        <option value="fade">Fade</option>
        <option value="slide">Slide</option>
    </select>
    
    <transition :name="alertAnimation">
        
    </transition>
    
    <script>
    	export default{
            data(){
                return {
                    alertAnimation:'fade'
                }
            }
        }
    </script>
    

    在属性名称前面加冒号,可以进行动态绑定。

    8.多个元素之间的过渡

    使用v-if进行状态之间的切换。或者使用v-if或者v-else,这个取反的状态v-show是不行的。vue只会替换内容,不会替换元素。

    <transition name= "fade" mode="out-in">
        <div v-if="show" key="info">
        </div>
         <div v-else key="warning">
        </div>
    </transition>
    

    mode属性

    out-in:旧元素的动画先执行,然后再插入新元素

    in-out:相反

    9.监听过渡事件的钩子

    用javaScript在上面添加动画。可以把钩子和css动画一起使用,可以在钩子内执行其他的代码

    添加元素

    • before-enter(仅仅执行一帧)
    • enter(播放动画)
    • after-enter(动画执行结束之后)
    • after-enter-cancelled(动画没有播放完,但是添加元素的条件却改变了)

    移除元素

    • before-leave
    • leave
    • after-leave
    • after-leave-cancelled
    <transition 
    	@before-enter="beforeEnter"
    	@enter="enter"
    	@after-enter="afterEnter"
    	@enter-cancelled="enterCancelled"
    	
    	@before-leave="beforeLeave"
    	@leave ="leave"
    	@after-leave="afterLeave"
    	@leave-cancelled="leaveCancelled">
        <div v-if="show" key="info">
        </div>
         <div v-else key="warning">
        </div>
    </transition>
    
    <script>
    	export default{
            data(){
                return {
                    alertAnimation:'fade'
                }
            },
            methods:{
                beforeEnter(el){
                    
                },
                enter(el,done){
                    //执行done方法来告诉Vue动画时长结束,随后使用after钩子
                    done();
                },
                leave(el,done){
            
        }
            }
        }
    </script>
    

    10.从动画中去掉css

    不写name属性,不代表不会寻找css类,Vue会寻找v-enter 、v-enter-active等css类。

    :css="false"跳过css的检测,意味着,Vue不用寻找CSS类,直接执行钩子就可以了。

    属性绑定:用冒号是因为,这里传递的是布尔值,而不是字符串。

    11.在JS中创建动画

    <script>
    	export default{
            data(){
                return {
                   elementWidth:100
                }
            },
            methods:{
                beforeEnter(el){
                    this.elementWidth = 100;
                    //重置状态
                    el.style.width = this.elementWidth+'px';
                },
                enter(el,done){
    				let round = 1;
    				const interval = setInterval(()=>{
    					el.style.width = (this.elementWidth + round * 10)+'px';
    					round++;
    					if (round >20){
    					clearInterval(interval);
    					done();
    					}
    				},20);
                },
                beforeLeave(el){
                	this.elementWidth = 300;
                    el.style.width = '300px';
                }
                leave(el,done){
            			let round = 1;
    				const interval = setInterval(()=>{
    					el.style.width = (this.elementWidth - round * 10)+'px';
    					round++;
    					if (round >20){
    					clearInterval(interval);
    					done();
    					}
    				},20);
        }
            }
        }
    </script>
    

    12.让动态组件做动画

    <button
            @click="selectedComponent == 'app-success-alert'?selectedComponent = 'app-danger-alert':selectedComponent = 'app-success-alert'">
        toggle
    </button>
    
    <component :is="selectedComponent">
    </component>
    

    13.列表动画

    <transition-group>
        <li v-for="(number,index) in numbers"
            @click="removeItem(index)"
            style="cursor:pointer"
            :key="number">{{number}}</li>
    </trnasition-group>
    <button @click="addItem">
        Add item
    </button>
    
    
    numbers:[1,2,3,4,5]
    
    addItem(){
        const pos =Math.floor(Math.random()*this.numbers.length);
        this.numbers.splice(pos,0,this.numbers.length + 1);
    },
    
    removeItem(index){
        this.numbers.splice(index,1)
        
    }
    

    transition-grouptransition 的运行机制相同,可以使用类似的css类,javascript 钩子也可以复用,两者之间只有名称的区别,而这个区别仅仅是针对Vue的。

    一个区别是,transition不会渲染到DOM,transition-group会渲染到一个HTML标签,默认是span,可以用来更改。

    在相同类型的HTML元素之间切换时,比如都是div标签,我们必须给他们添加key属性,让vue能够区分它们。在transition-group内,我们必须给所有元素添加key属性,即便用的是不同类型的标签,也必须在这里添加ley属性,否则Vue就无法区分列表中的单个元素。之所以要区分这些元素,是因为当给他们添加动画时,还需要移动现存的对象,要保证移动的是正确的对象,这样就需要Key属性

    transition-group内可以使用新的css类

    //添加到所有需要改变位置的元素上
    .slide-move{
    	transition:transform 1s;
    }
    //删除时更流畅,正在删除的元素不占用文档流
    //播放动画时,其他元素可以穿过他的位置
    .slide-leave-active{
    	position:absolute;
    }
    

    vue在背后使用 transform来移动元素