登录
原创

vue-单元素/单组件/列表动画

发布于 2021-11-23 阅读 405
  • 前端
  • Vue.js
原创

单元素/单组件动画用 transition

可以用在单元素/单组件的外层,然后结合vue定义好的类名,来控制动画效果。
类名:
.v-enter-from - - -动画入场开始状态
.v-enter-to - - -动画入场结束状态
.v-enter-active - - -动画入场过程状态

.v-leave-from - - -动画出场开始状态
.v-leave-to - - -动画出场结束状态
.v-leave-active - - -动画出场过程状态

入场:从无到到有
出场:从有到无

类名默认是 “v” 开头,如果想要自定义类名,可以设置 transition 的 “name” 属性

eg:
默认:

<transition>
  <div>今天也是元气满满的一天呀!!!</div>
</transition>

自定义名称:

<transition name="good">
  <div>今天也是元气满满的一天呀!!!</div>
</transition>

该类名对应为:

.good-enter-from - - -动画入场开始状态
.good-enter-to - - -动画入场结束状态
.good-enter-active - - -动画入场过程状态

.good-leave-from - - -动画出场开始状态
.good-leave-to - - -动画出场结束状态
.good-leave-active - - -动画出场过程状态

如果想要页面首次出现时也有动画效果,可以用- - - appear

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>单元组的入场出场封装</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
</body>
<style>
  .v-enter-from {
    opacity: 0
  }
  /*  可省略
  .v-enter-to {
    opacity: 1
  } */
  .v-enter-active, .v-leave-active {
    transition: opacity 3s ease-out
  }
  /* 可省略
  .v-leave-from {
    opacity: 1;
  } */
  .v-leave-to {
    opacity: 0;
  }
  .day {
    padding: 20px;
    color: palevioletred;
  }
</style>
<script>
  const app = Vue.createApp({
    data() {
      return {
        show: true
      }
    },
    methods: {
      handleClick() {
        this.show = !this.show
      }
    },
    template: `
    <div>
      <transition appear>
        <div v-if="show" class="day">今天也是元气满满的一天呀!!!</div>
      </transition>
      <button @click="handleClick">点击显示/隐藏</button>
    </div>
    `
  })
  const vm = app.mount('#root')
</script>
</html>

页面效果:

单元素动画.gif

多个单元素的切换

eg:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>多个单元素/单组件切换</title>
  <script src="https://unpkg.com/vue@next"></script>
  <style>
    .v-enter-from,
    .v-leave-to {
      opacity: 0;
    }
    .v-enter-active,
    .v-leave-active {
      transition: opacity 3s ease-in;
    }
    .v-enter-to,
    .v-leave-from {
      opacity: 1;
    }
  </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const app = Vue.createApp({
    data() {
      return {
        show: false
      }
    },
    methods: {
      handleClick() {
        this.show = !this.show
      }
    },
    template: `
    <div>
      <transition>
        <div v-if="show">你好,我是波吉</div>
        <div v-else>你好,我是卡克</div>  
      </transition>
      <button @click="handleClick">点击切换</button>
    </div>
    `
  })
  const vm = app.mount('#root')
</script>
</html>

页面效果:

多个单元素切换.gif

多个单组件的切换

eg:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>多个单组件之间切换</title>
  <script src="https://unpkg.com/vue@next"></script>
  <style>
    .v-enter-from,
    .v-leave-to {
      opacity: 0;
    }
    .v-enter-active,
    .v-leave-active {
      transition: opacity 1s ease-in;
    }
    .v-enter-to,
    .v-leave-from {
      opacity: 1;
    }
  </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const componentA = {
    template: '<div>你好,我是波吉</div>'
  }
  const componentB = {
    template: '<div>你好,我是卡克</div>'
  }
  const app = Vue.createApp({
    data() {
      return {
        component: 'component-a'
      }
    },
    methods: {
      handleClick() {
        if(this.component === 'component-a') {
          this.component = 'component-b'
        } else {
          this.component = 'component-a'
        }
      }
    },
    components: {
      'component-a': componentA,
      'component-b': componentB
    },
    template: `
    <transition mode="out-in" appear>
      <component :is="component" />
    </transition>
    <button @click="handleClick">点击切换</button>
    `
  })
  const vm = app.mount('#root')
</script>
</html>

页面效果:

多个单组件切换.gif

控制入场出场顺序:mode

默认情况下,入场出场是同时进行的,可以使用 “mode” 设置入场、出场顺序
mode=“out-in” - - - 先出场,再入场
mode=“in-out”- - -先入场,再出场

第一次进入也有动画:appear

多个元素动画用transition-group

代码示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>列表动画</title>
  <script src="https://unpkg.com/vue@next"></script>
  <style>
    .list-item {
      display: inline-block;
      width: 60px;
      height: 60px;
      line-height: 60px;
      margin-right: 10px;
      text-align: center;
      border: 1px solid green;
      background-color: #eee;
      border-radius: 30px;
    }
    .v-enter-from, .v-leave-to {
      opacity: 0;
      transform: translateY(30px);
    }
    .v-enter-active, .v-leave-active {
      transition: all .5s ease;
    }
    .v-enter-to, .v-leave-from {
      opacity: 1;
      transform: translateY(0);
    }
    .v-move {
      transition: all .5s ease;
    }
    .v-leave-active {
      position: absolute;
    }
    </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  /* const app = Vue.createApp({
    data() {
      return {
        list: [1, 2, 3]
      }
    },
    methods: {
      handleClickAdd() {
        this.list.unshift(this.list.length + 1)
      },
      handleBClickRemove() {
        this.list.shift(this.list.length)
      }
    },
    template: `
    <div>
      <transition-group>
        <span v-for="(item, index) in list" :key="index" class="list-item">烦恼{{item}}</span>
      </transition-group>
      <button @click="handleClickAdd">点击增加</button>
      <button @click="handleBClickRemove">点击减少</button>
    </div>
    `
  }) */
  // 列表动画的实现
  const app = Vue.createApp({
    data() {
      return { list: [1, 2, 3] }
    },
    methods: {
      handleClickAdd() {
        this.list.unshift(this.list.length + 1)
      },
      handleBClickRemove() {
        this.list.shift(this.list.length)
      }
    },
    template: `
      <div>
        <transition-group>
          <span class="list-item" v-for="item in list" :key="item">烦恼{{item}}</span>
        </transition-group>
        <button @click="handleClickAdd">增加</button>
        <button @click="handleBClickRemove">减少</button>
      </div>
    `
  });
  const vm = app.mount('#root')
</script>

</html>

页面效果:

动画列表.gif

注意 v-for循环 不要使用 index 作为key值

使用index作为键值的话,删除添加的动画效果都会是最后面的一个元素,前面真正添加/删除的元素没有该有的动画效果

eg:

动画列表误.gif

注意元素入场/出场时,其他元素也缓速移动位置:.v-move

出场其他元素缓动还要加上:

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

评论区

零00
7粉丝

时光荏苒,我自清欢

0

1

0

举报