过渡

作者: sweetBoy_9126 | 来源:发表于2018-10-29 22:35 被阅读9次

    过渡的要点:

    1. 需要进行动画的元素外面要加一个<transition>标签
    2. 需要进行动画的元素必须使用v-if或v-show
    3. 进入动画就是一个元素从没有到有的过程,如果一开始这个元素不显示那么执行的就是进入动画
    4. 离开动画就是一个元素从有到没有的过程,如果一开始这个元素显示,那么执行的就是离开动画
    5. 多个相同标签的元素做动画,需要给每一个标签加一个key里面是唯一值
    6. -enter-to(进入结束)和-leave(离开之前)一般不需要写,因为他们都是默认状态
    7. 对于css过渡 -enter-leave-to是一样的状态,-enter-active-leave-active也是一样的状态,所以他们可以两两合写在一起
      比如:
      .fade-enter-active, .fade-leave-active{ transition: all 1s; }
      .fade-enter, .fade-leave-to{ opacity: 0; }
    8. 对于animation只需要使用-enter-active-leave-active然后分别引入同一个动画,只不过离开的时候将这个动画reverse一下

    进入动画(enter)
    进入之前:-enter
    进入结束:-enter-to


    image.png

    离开动画(leave)

    image.png

    通过@transitionend来执行过渡完成后的方法
    如果想让一个动画每次滚动回来都执行的话,那么就要使用过渡提供的js钩子

    <transition
      v-on:before-enter="beforeEnter"
      v-on:enter="enter"
      v-on:after-enter="afterEnter"
      v-on:enter-cancelled="enterCancelled"
    
      v-on:before-leave="beforeLeave"
      v-on:leave="leave"
      v-on:after-leave="afterLeave"
      v-on:leave-cancelled="leaveCancelled"
    >
      <!-- ... -->
    </transition>
    
    // ...
    methods: {
      // --------
      // 进入中
      // --------
    
      beforeEnter: function (el) {
        // ...
      },
      // 当与 CSS 结合使用时
      // 回调函数 done 是可选的
      enter: function (el, done) {
        // ...
        done()
      },
      afterEnter: function (el) {
        // ...
      },
      enterCancelled: function (el) {
        // ...
      },
    
      // --------
      // 离开时
      // --------
    
      beforeLeave: function (el) {
        // ...
      },
      // 当与 CSS 结合使用时
      // 回调函数 done 是可选的
      leave: function (el, done) {
        // ...
        done()
      },
      afterLeave: function (el) {
        // ...
      },
      // leaveCancelled 只用于 v-show 中
      leaveCancelled: function (el) {
        // ...
      }
    }
    

    一个案例:
    封装一个fullpage组件,里面使用transition-group,需要监听每次进去当前页面和离开,所以只需用到enter和leave钩子,然后在data里声明一个state初始值是'',当enter钩子执行时state的值就是enter,leave就是leave,然后将这个state传到slot插槽上,这样其它的组件可以直接在fullpage的作用域下得到它的state了,如下

    fullpage.vue
    <template>
    <transition-group tag="div" :name="name"
            @enter="enter"
            @leave="leave"
     >
      <div v-for="(list,index) in 5" v-show="index === 1" @transitionend="end"></div>
      <slot :state="state"></slot>
    </transition-group>
    </template>
    <script>
      export default{
        data(){
          return {
            state: ''
          }
        },
        methods: {
          enter(el,done){
            this.state = 'enter'
          },
          leave(el,done){
            this.state = 'leave'
          },
          end(){
            this.state = 'transitionend'
          }
        }
      }
    </script>
    

    这时候如果另外有一个组件有动画效果或内容要加在这个fullpage组件上,就通过slot来使用,下面将另一个组件命名为page1

    index.html
    <div id="app">
      <Fullpage>
        //这里通过slot-scope将组件的作用域绑定到Fullpage上,只要下面通过prop.访问的都是组件内的数据
        <template slot-scope="prop">
          <page1 :state="prop.state"></page1>
        </template>
      </Fullpage>
    </div>
    

    然后只要在page1组件里的props传入这个state就可以拿到了,之后就在page1组件里使用watch监听state,如果是state是enter就执行动画,否则就移除

    page1.vue
    export default{
      props: ['state'],
      watch: {
        state(){
          if(this.state=== 'enter'){
            //要执行的动画
          }else{
            //结束动画
          }
        }
      }
    }
    
    css animation的使用
    • 自定义animation
    1. 只需要写enter-active和leave-active就行
    2. 定义的animation动画结束的时候一定要是正常状态
    3. 进入和离开只需要用同一个动画,只不过有一个是相反就行
      比如:
    <style>
    .bounce-enter-active {
      animation: bounce-in .5s;
    }
    .bounce-leave-active {
      animation: bounce-in .5s reverse;
    }
    @keyframes bounce-in {
      0% {
        transform: scale(0);
      }
      50% {
        transform: scale(1.5);
      }
      100% {
        transform: scale(1);
      }
    }
    </style>
    <div id="example-2">
      <button @click="show = !show">Toggle show</button>
      <transition name="bounce">
        <p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.</p>
      </transition>
    </div>
    <script>
    new Vue({
      el: '#example-2',
      data: {
        show: true
      }
    })
    </script>
    
    • 使用第三方库
      只需要在transition标签里使用enter-acitve-class和leave-active-class指定它们使用的库里面的类名就行
    <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
    
    <div id="example-3">
      <button @click="show = !show">
        Toggle render
      </button>
      <transition
        enter-active-class="animated tada"
        leave-active-class="animated bounceOutRight"
      >
        <p v-if="show">hello</p>
      </transition>
    </div>
    

    多个元素的过渡

    注意:
    1.如果有相同标签名的元素切换时,需要通过key设置唯一的值区分
    2.旧元素的离开和新元素的进入动画会同时执行,所以我们需要给<transition>标签加一个mode

    in-out:新元素先进行过渡,完成之后当前元素过渡离开。
    out-in:当前元素先进行过渡,完成之后新元素过渡进入。

    <style>
    .fade-enter-active,.fade-leave-active{
      transition: all .3s linear;
    }
    .fade-enter{
      opacity: 0;
    }
    .fade-leave-to{
      opacity: 0;
    }
    
    </style>
    <div id="app">
        <transition name="fade" mode="out-in">
          <button v-if="status === 'out'" @click="status='in'" key="out">out</button>
          <button v-else @click="status = 'out'" key="in">in</button>
        </transition>
      </div>
      <script>
        let app = new Vue({
           el: '#app',
           data: {
             status: 'out'
           }
         })
      </script>
    

    多个组件的过渡

    通过给component标签外加transition标签,然后给component加一个动态is属性,通过is绑定的属性更改组件

    <div id="app">
        <button @click="view='v-a'">A</button>
        <button @click="view='v-b'">B</button>
        <transition name="fade" mode="out-in">
          <component :is="view"></component>
        </transition>
      </div>
      <script>
        let app = new Vue({
           el: '#app',
           data: {
             view: 'v-a'
           },
          components: {
            'v-a': {
              template: '<div>Component A</div>'
            },
            'v-b': {
               template: '<div>Component B</div>'
            }
          }
         })
      </script>
    

    列表过渡

    1. 需要过渡的外层使用<transition-group>,它默认会显示为span标签,你也可以通过 tag 特性更换为其他元素。
    2. 不可以使用mode
    3. 必须绑定key
    4. transition-troup标签内必须紧跟for循环
    <style>
    .list-item {
      display: block;
      margin-right: 10px;
    }
    .list-enter-active, .list-leave-active {
      transition: all 1s;
    }
    .list-enter, .list-leave-to
    {
      opacity: 0;
      transform: translateX(90%);
    </style>
    <div id="list-demo" class="demo">
        <button v-on:click="add">Add</button>
        <button v-on:click="remove">Remove</button>
        <transition-group name="list" tag="p">
          <span v-for="item in items" v-bind:key="item" class="list-item">
          {{ item }}
        </span>
        </transition-group>
      </div>
      <script>
        new Vue({
      el: '#list-demo',
      data: {
        items: [1,2,3,4,5,6,7,8,9],
        nextNum: 10
      },
      methods: {
        randomIndex: function () {
          return Math.floor(Math.random() * this.items.length)
        },
        add: function () {
          this.items.splice(this.randomIndex(), 0, this.nextNum++)
        },
        remove: function () {
          this.items.splice(this.randomIndex(), 1)
        },
      }
    })
      </script>
    

    相关文章

      网友评论

          本文标题:过渡

          本文链接:https://www.haomeiwen.com/subject/ktaitqtx.html