Vue-基础入门(中)--Part.2(1-4)

2-1 使用 Vue 实现基础的 CSS 过渡与动画效果

过渡和动画是什么?

过渡:一个div的颜色从黑色变成红色

动画:一个div元素左右移动

举个简单的动画例子:

<style>
  @keyframes leftToRight {
    0% {
      transform: translateX(0);
    }
    50% {
      transform: translateX(-50px);
    }
  }
  .animation {
    animation: leftToRight 3s;
  }
</style>
<script>
  const app = Vue.createApp({
    data () {
      return {
        animate: {
          animation: true
        }
      }
    },
    template: `
      <div :class="animate">hello Jennie</div>
    `
  })

  const vm = app.mount('#root');
</script>

这个动画就是很简单的…可以自己试试^ ^

然后就是这个@keyframes做一个简单的解释:

以百分比来规定改变发生的时间,或者通过关键词"from"和"to",等价于0%和100%

0%是动画的开始时间,100%动画的结束时间

然后再举个过渡的例子:

<style>
  .transition {
    transition: 3s background-color ease;
  }
  .blue {
    background:blue;
  }
  .green {
    background: green;
  }
</style>
<script>
  const app = Vue.createApp({
    data () {
      return {
        animate: {
          transition: true,
          blue: true,
          green: false
        }
      }
    },
    methods: {
      handleBtnClick() {
        this.animate.blue = !this.animate.blue
        this.animate.green = !this.animate.green
      }
    },
    template: `
      <div :class="animate">hello Jennie</div>
      <button @click="handleBtnClick">切换</button>
    `
  })

  const vm = app.mount('#root');
</script>

这个也挺简单的,试一下就行了

其实上面的跟直接用css写差不多的,上面我是通过控制class来修改样式的,那能不能直接控制style呢? 是可以的(`・ω・´)

<head>
  <style>
    .transition {
      transition: 3s background-color ease;
    }
    .blue {
      background:blue;
    }
    .green {
      background: green;
    }
  </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const app = Vue.createApp({
    data () {
      return {
        styleObj: {
          background: 'blue'
        }
      }
    },
    methods: {
      handleBtnClick() {
        this.styleObj.background === 'blue' ? this.styleObj.background = 'green' : this.styleObj.background = 'blue'
      }
    },
    template: `
      <div class="transition" :style="styleObj">hello Jennie</div>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>

太基础了,看看就行了

2-2 使用 transition 标签实现单元素/组件的过渡和动画效果

过渡效果

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://unpkg.com/vue@next"></script>
  <style>
    .v-enter-from {
      opacity: 0;
    }
    .v-enter-active {
      transition: opacity 3s ease-out;
    }
    .v-enter-to {
      opacity: 1;
    }
    .v-leave-from {
      opacity: 1;
    }
    .v-leave-active {
      transition: opacity 3s ease-out;
    }
    .v-leave-to {
      opacity: 0;
    }
  </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const app = Vue.createApp({
    data () {
      return {
        show: false
      }
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show
      }
    },
    template: `
      <transition>
        <div v-if="show">hello Jennie</div>
      </transition>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>
</html>

其实这个很简单,但是还是记录一下:

  1. v-enter-from:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
  3. v-enter-to:定义进入过渡的结束状态。在元素被插入之后下一帧生效(与此同时v-enter-from被移除),在过渡/动画完成之后移除。
  4. v-leave-from:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
  6. v-leave-to:离开过渡的结束状态。在离开过渡被触发之后下一帧生效(与此同时v-leave-from被删除),在过渡/动画完成之后移除。

在这里插入图片描述

对于上面<style>里的代码其实还可以简化一下:

<style>
  .v-enter-from {
    opacity: 0;
  }
  .v-enter-active,
  .v-leave-active {
    transition: opacity 3s ease-out;
  }
  .v-enter-to {
    opacity: 1;
  }
  .v-leave-to {
    opacity: 0;
  }
</style>

这里的v-enter-to其实也可以删掉,但是涉及一些原理性的东西,后面再探讨

动画效果:

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://unpkg.com/vue@next"></script>
  <style>
    @keyframes shake {
      0% {
        transform: translateX(-100px);
      }
      50% {
        transform: translateX(-50px);
      }
      100% {
        transform: translateX(50px);
      }
    }
    .v-enter-active,
    .v-leave-active {
      animation: shake 3s ;
    }
  </style>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const app = Vue.createApp({
    data () {
      return {
        show: false
      }
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show
      }
    },
    template: `
      <transition>
        <div v-if="show">hello Jennie</div>
      </transition>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>
</html>

补充一个:

对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些class名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter-from应该写成 my-transition-enter-from

然后就是我们还可以自定义过渡class类名

<style>
  @keyframes shake {
    0% {
      transform: translateX(-100px);
    }
    50% {
      transform: translateX(-50px);
    }
    100% {
      transform: translateX(50px);
    }
  }
  .hello,
  .by {
    animation: shake 3s ;
  }
</style>

 template: `
   <transition
     enter-active-class="hello"
     leave-active-class="bye"
   >
     <div v-if="show">hello Jennie</div>
   </transition>
   <button @click="handleBtnClick">切换</button>
 `

用这种自定义class类名一个很方便的地方是可以引用第三方动画库,举个例子(百度搜索animate.css):

// 头部引用
<link
  rel="stylesheet"
  href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
// 之前写的style可以删除了
template: `
  <transition
    enter-active-class="animate__animated animate__bounce"
    leave-active-class="animate__animated animate__bounce"
  >
    <div v-if="show">hello Jennie</div>
  </transition>
  <button @click="handleBtnClick">切换</button>
`

这样引用第三方的动画库是很方便的^ ^

然后回到一开始,我们看下面的代码:

.v-enter-from {
  color: red;
}
.v-enter-active{
  animation: shake 3s;
  transition: color 3s ease-in;
  color: green;
}

这样写是不会显示红色的,动画在入场的时候就是绿色,因为v-enter-from是包含在v-enter-active里面的,所以绿色会覆盖掉红色

接下来我们看一下这种情况:

.v-enter-from {
  color: red;
}
.v-enter-active{
  animation: shake 10s;
  transition: color 3s ease-in;
}
.v-leave-active {
  color: red;
  animation: shake 10s;
  transition: color 3s ease-out;
}

这个过渡和动画的时间不一致,我们运行之后会发现,实际上整体的时间是以时间长的那个为准的,也就是过渡执行了3s,动画执行了10s。那我们可以自己控制这个时长吗?是可以的^ ^

第一种是:

<transition type="transition">
  <div v-if="show">hello Jennie</div>
</transition>

type="transition">的意思是以transition为准,运行结果就是3s之后动画也停止了

第二种是:

<transition duration="1000">
  <div v-if="show">hello Jennie</div>
</transition>

入场和出场时间固定为1s

第三种是:

<transition :duration="{enter: 3000,leave: 4000}">
  <div v-if="show">hello Jennie</div>
</transition>

入场出场时间自定义^ ^

其实上面的方法都是用css来执行动画过渡效果的,那么我们怎么用js来控制呢?

首先是关闭使用css制作动画<transition :css="false">

<script>
  const app = Vue.createApp({
    data() {
      return {
        show: false
      }
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show
      },
      handleBeforeEnter(el) {
        el.style.color = 'red'
      },
      handleEnterActive(el, done) {
        const animation = setInterval(() => {
          const color = el.style.color
          if(color === 'red') {
            el.style.color = 'green'
          } else {
            el.style.color = 'red'
          }
        }, 1000)
        setTimeout(() => {
          clearInterval(animation);
          done()
        }, 3000)
      },
      handleEnterEnd() {
        alert(123)
      }
    },
    template: `
      <transition
        :css="false"
        @before-enter="handleBeforeEnter"
        @enter="handleEnterActive"
        @after-enter="handleEnterEnd"
      >
        <div v-if="show">hello Jennie</div>
      </transition>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>

@before-enter@enter@after-enter,这三个钩子就不介绍了,应该能懂,讲一下setInterval是在执行颜色切换的效果,setTimeout是设置过渡结束的时间,这个参数done,也就是在setTimeout里执行了done()是让transition感知到动画已经结束了,才会继续执行后面@after-enter钩子里的代码

还需要注意到的一点是@before-enter@after-enter执行的方法只接收一个参数el@enter接收两个参数eldone,下面的出场一样

对应的还有三个出场的钩子@before-leave@leave@leave-after,就不细说了,自己去试试就知道了^ ^

2-3 组件和元素切换动画的实现

先看第一种多个元素切换:

<head>
  <script src="https://unpkg.com/vue@next"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
  <style>
    .v-enter-from,
    .v-leave-to {
      opacity: 0;
    }

    .v-enter-active,
    .v-leave-active {
      transition: opacity 1s ease-in;
    }

    .v-leave-from,
    .v-enter-to {
      opacity: 1;
    }
  </style>
</head>

<body>
  <div id="root"></div>
</body>
<script>
  const app = Vue.createApp({
    data() {
      return {
        show: true
      }
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show
      },
    },
    template: `
      <transition>
        <div v-if="show">hello Jennie</div>
        <div v-else>Meiko</div>
      </transition>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>

这样写运行出来还挺丑的,第二个div出现的时候,第一个div并没有完全消失,我们可以这样做:

<transition mode="out-in">就ok了,然后就是在刚进入页面的时候,第一个div展示是没有过渡效果的,我们可以再加一个<transition mode="out-in" appear>这样就行了

最后再说一下组件之间的切换

<script>
  const componentA = {
    template: `<div>hello Jennie</div>`
  }
  const componentB = {
    template: `<div>Meiko</div>`
  }
  const app = Vue.createApp({
    data() {
      return {
        show: true
      }
    },
    components: {
      'component-a': componentA,
      'component-b': componentB
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show
      },
    },
    template: `
      <transition mode="out-in" appear>
        <component-a v-if="show" />
        <component-b v-else="show" />
      </transition>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>

其实还可以写的更简洁一点:(动态绑定组件)

<script>
  const componentA = {
    template: `<div>hello Jennie</div>`
  }
  const componentB = {
    template: `<div>Meiko</div>`
  }
  const app = Vue.createApp({
    data() {
      return {
        show: true,
        components: 'component-a'
      }
    },
    components: {
      'component-a': componentA,
      'component-b': componentB
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show
        this.components === 'component-a' ? this.components = 'component-b' : this.components = 'component-a'
      },
    },
    template: `
      <transition mode="out-in" appear>
        <component :is='components' />
      </transition>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>

哎,总之这些都挺基础的,看一看敲一敲就好了

2-4 状态动画

举个简单的例子:

<script>
  const app = Vue.createApp({
    data() {
      return {
        number: 1,
        currentNumber: 1
      }
    },
    methods: {
      handleBtnClick() {
        if (this.number < 10) {
          const animation = setInterval(() => {
            this.number += 1
            if(this.number === 10) {
              clearInterval(animation)
            }
          }, 100);
        }
      },
    },
    template: `
      <div>{{number}}</div>
      <button @click="handleBtnClick">切换</button>
    `
  })
  const vm = app.mount('#root');
</script>

状态动画可以理解为,通过改变数据来改变内容的展示,然后不断改变数据,内容也跟着改变,就形成了动画的效果,常用的svg图就是基于这种原理实现的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值