Vue-9【JS钩子、多元素组件、列表过渡、动画封装】

一.js钩子

(1).基础

js钩子可以用js来实现动画过渡

在transition上加入@before-enter/@enter/@after-enter =“xx”即可实现Js钩子

<div id="root">
        <transition @before-enter="beforeEnter"
                    @enter="enter"
                    @after-enter="afterEnter">
            <div v-if="show">helloWord</div>
        </transition>
        <button @click="handleBtnClick">click</button>
    </div>
    <script>
        let vm = new Vue({
            el:"#root",
            data:{
                show:true
            },
            methods:{
                handleBtnClick(){
                    this.show = !this.show
                },
                beforeEnter(el){
                    el.style.color='red'
                },
                enter(el,done){
                    setTimeout(()=>{
                        el.style.color="green"
                        done();
                    },2000)
                   
                },
                afterEnter(el){
                    setTimeout(()=>{
                        el.style.color="black"
                    },2000)
                }
            }
            
        })

退出改为leave即可,只有enter/leave才会接收两个参数,done用来结束enter/enter

(2).使用库Velocity.js

在响应方法中使用Velocity(el,{opacity:1},{duration:1000,complete:done})实现

 <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script>
</head>
<body>
    <div id="root">
        <transition @before-enter="beforeEnter"
                    @enter="enter"
                    @after-enter="afterEnter"
                    @before-leave="beforeLeave"
                    @leave="leave"
                    @after-leave="afterLeave">
            <div v-if="show">helloWord</div>
        </transition>
        <button @click="handleBtnClick">click</button>
    </div>
    <script>
        let vm = new Vue({
            el:"#root",
            data:{
                show:true
            },
            methods:{
                handleBtnClick(){
                    this.show = !this.show
                },
                beforeEnter(el){
                    el.style.opacity=0;
                },
                enter(el,done){
                   Velocity(el,{
                       opacity:1
                   },{
                       duration:1000,
                       compelete:done
                   })
                   
                },
                afterEnter(el){
                   
                },
                beforeLeave(el){
                  
                },
                leave(el,done){
                    Velocity(el,{
                       opacity:0
                   },{
                       duration:1000,
                       compelete:done
                   })
                },
                afterLeave(el){
                    
                }
            }
            
        })

    </script>

二.多元素组件

(1).在transition标签中通过if else实现基本切换动画

<style>
        .v-enter,
        .v-leave-to{
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active{
            transition: opacity 3s linear;
        }
    </style>
</head>
<body>
    <div id="root">
        <transition>
            <div v-if="show">helloWord</div>
            <p v-else>Bye</p>
        </transition>
        <button @click="handleBtnClick">click</button>
    </div>
    <script>
        let vm = new Vue({
            el:"#root",
            data:{
                show:true
            },
            methods:{
                handleBtnClick(){
                    this.show = !this.show
                }
            }
            
        })

    </script>

(2).key=""解决相同元素动画失效

p换为div后就会失效

<transition>
            <div v-if="show">helloWord</div>
            <div v-else>Bye</div>
        </transition>

用key来解决

 

<transition>
            <div v-if="show" key="hello">helloWord</div>
            <div v-else key="bye">Bye</div>
        </transition>

(3).按钮On Off切换

<style>
        .wrapper{
            position: relative;
            width: 31px;
            height: 22px;
        }
        button{
            position: absolute;
            top: 0;
            left: 0;
        }
        .v-enter,
        .v-leave-to{
            opacity: 0;
        }
        .v-enter-active,
        .v-leave-active{
            transition: opacity 1s linear;
        }
    </style>
</head>
<body>
    <div id="root">
        <div class="wrapper">
            <transition>
                <button v-if="show" key="on" @click="onClick">on</button>
                <button v-else key="off" @click="onClick">off</button>
            </transition>
        </div>
        
    </div>
    <script>
        let vm = new Vue({
            el:"#root",
            data:{
                show:true
            },
            methods:{
                onClick(){
                    this.show = !this.show
                }
            }
            
        })

    </script>

(4).按钮On Off切换升级版本

<style>
        .wrapper{
            position: relative;
            width: 31px;
            height: 22px;
        }
        button{
            position: absolute;
            top: 0;
            left: 0;
        }
        .v-enter{
            transform: translateX(31px);
        }
        .v-leave-to{
            transform: translateX(-31px);
        }
        .v-enter-active,
        .v-leave-active{
            transition: all 1s linear;
        }
    </style>
</head>
<body>
    <div id="root">
        <div class="wrapper" mode="out-in">
            <transition>
                <button v-if="show" key="on" @click="onClick">on</button>
                <button v-else key="off" @click="onClick">off</button>
            </transition>
        </div>
        
    </div>
    <script>
        let vm = new Vue({
            el:"#root",
            data:{
                show:true
            },
            methods:{
                onClick(){
                    this.show = !this.show
                }
            }
            
        })

    </script>

其中如果在transition标签上加入 mode=“out-in/in-out”属性即先将out执行完再执行In,如果不加同时触发

(5).两个组件的过渡

通过component :is标签嵌套再transition标签中完成

 <style>
       
        .v-enter,
        .v-leave-to{
            opacity: 0;
        }
        
        .v-enter-active,
        .v-leave-active{
            transition: opacity 1s linear;
        }
    </style>
</head>
<body>
    <div id="root">
        <div class="wrapper">
            <transition  mode="out-in">
                <component :is="type"></component>
            </transition>
            <button @click="onClick">click</button>
        </div>
        
    </div>
    <script>
        Vue.component('child-one',{
            template:'<div>One</div>'
        })
        Vue.component('child-two',{
            template:'<div>Two</div>'
        })
        let vm = new Vue({
            el:"#root",
            data:{
                type:'child-one'
            },
            methods:{
                onClick(){
                    this.type = (this.type === 'child-one' ? 'child-two': 'child-one');
                }
            }
            
        })
     
    </script>

三.列表过渡

在一个transition中同时存在多个相同标签,既要用<transition-group>标签

(1).要求在列表添加的过程中加过渡

<style>
       
        .v-enter,
        .v-leave-to{
            opacity: 0;
        }
        
        .v-enter-active,
        .v-leave-active{
            transition: opacity 1s linear;
        }
    </style>
</head>
<body>
    <div id="root">
        <div class="wrapper">
            <ul>
                <transition-group  mode="out-in">
                    <li v-for="item of list" :key="item.id">{{item.text}}</li>
                </transition-group>
            </ul>
            <button @click="onClick">click</button>
        </div>
        
    </div>
    <script>
        let count = 0;
        let vm = new Vue({
            el:"#root",
            data:{
                list:[]
            },
            methods:{
                onClick(){
                   this.list.push({
                       text:'123',
                       id:count++
                   })
                }
            }
            
        })
     
    </script>

做的事情其实就是给每个li上面添加了一个transition

四.动画封装

(1).封装

通过组件的模板将标签放入,且结合钩子函数和插槽实现封装

 <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script>
</head>
<body>
    <div id="root">
      
           <fade :show="show">
               <div>HElloWorld</div>
           </fade>
            <button @click="onClick">click</button>
      
        
    </div>
    <script>
        Vue.component('fade',{
            props:['show'],
            template:`
            <transition name="fade"
                        @beforeEnter="beforeEnter"
                        @enter="enter"
                        @afterEnter="afterEnter"
                        @beforeLeave="beforeLeave"
                        @leave="leave"
                        @afterLeave="afterLeave">
                <slot v-if="show"></slot>
            </transition>
            `,
            methods:{
                beforeEnter(el){
                    el.style.opacity=0;
                },
                enter(el,done){
                    Velocity(el,{
                        opacity:1
                    },{
                        duration:1000,
                        templete:done
                    })
                },
                afterEnter(el){

                },
                beforeLeave(el){
                    
                },
                leave(el,done){
                    Velocity(el,{
                        opacity:0
                    },{
                        duration:1000,
                        templete:done
                    })
                },
                afterLeave(el){

                }

            }
        })
        let vm = new Vue({
            el:"#root",
            data:{
                show:true
            },
            methods:{
                onClick(){
                   this.show = !this.show
                }
            }
            
        })
     
    </script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值