Skip to content

Latest commit

 

History

History
860 lines (685 loc) · 32 KB

File metadata and controls

860 lines (685 loc) · 32 KB

六、过渡和动画

在本章中,我们将了解如何在 Vue 中使用过渡和动画。这是一个很大的话题,需要比一章多得多的篇幅才能涵盖。因此,我们将处理一些基本概念,我们可以在未来建立这些概念。

我们将重点关注以下主题:

  • 了解 CSS 转换和动画
  • 使用transition组件实现转换
  • 在 Vue 中使用 CSS 转换和动画
  • 与第三方 CSS 和 JS 库集成
  • 绑定 CSS 样式
  • 与过渡小组合作
  • JavaScript 动画挂钩

阅读本章后,您应该对如何在 Vue 中使用过渡和动画有了深入的了解。

CSS 中的过渡和动画

为了了解 Vue.js 如何处理过渡和动画,我们首先需要快速复习一下它们在 CSS 中的工作方式。我们将重点介绍最基本的内容,目的是重新探讨控制过渡和动画的原则。我们还将研究它们的差异。我们的目标是能够更好地理解 Vue 的帮助,而不是深入了解过渡和动画的细微差别

CSS 转换如何工作

当我们将鼠标悬停在一个元素上时,我们将该元素置于悬停状态。当用户通过与我们的网页交互触发悬停状态时,我们可能需要强调这种状态变化已经发生。

为了强调状态的变化,我们可以,例如,当用户悬停在该元素上时,更改该元素的 CSSbackground-color属性。

这就是 CSS 转换的用武之地。当我们为 CSS 转换编写代码时,我们指示浏览器如何显示对我们示例中特定 CSS 属性background-color属性所做的更改。

假设我们有一个 HTMLbutton元素。此元素的 CSS 属性background-color设置为red

button {
  background-color: red;
}

当用户将鼠标悬停在按钮上方时,我们希望将background-color属性的值从red更改为blue。我们将这样做:

button:hover {
  background-color: blue;
}

示例代码在此处可用:https://codepen.io/AjdinImsirovic/pen/LJKJYY

然而,这种颜色的变化是突然的。为了将 HTML 元素的 CSS 属性从一个值平滑地过渡到另一个值,我们使用 CSStransition属性。transition属性是一个速记 CSS 属性。这只是我们在目标元素上指定的另一个 CSS 属性,我们希望将此平滑转换应用到该元素

在我们的例子中,我们希望平滑地将按钮从红色背景转换为蓝色背景。我们只需在 button 元素上添加速记transition属性,并在此transition属性上设置两个值:

button {
 background-color: red;
 transition: background-color 4s;
}
button:hover {
 background-color: blue;
}

这是公式:

transition: property-to-transition transition-duration, property-to-transition transition-duration

在我们的示例中,我们只指定了一个属性的持续时间,但我们可以根据需要添加更多属性 https://codepen.io/AjdinImsirovic/pen/rqBqYN

CSS 动画如何工作

在前面的示例中,我们看到了一个简单的转换。在本例中,我们将转换转换为动画。更新后的 CSS 代码如下所示:

button {
  background-color: red;
}
button:hover {
  animation: change-color 4s;
}
@keyframes change-color {
  0% {
    background: red;
  }
  100% {
    background: blue;
  }
}

在前面的代码中,我们已经将简单的 CSS 转换转换为 CSS 动画

此示例可在以下链接中找到:https://codepen.io/AjdinImsirovic/pen/WaNePm

然而,它的工作原理并非 100%相同。当我们将鼠标悬停在按钮上时,我们不会得到与转换示例中完全相同的行为。原因是我们已经指定了动画的初始状态(作为0%和最终状态(作为100%。因此,我们有效地将过渡示例中的行为映射到动画示例中的行为

但是,当我们从按钮上移除鼠标指针时,动画不会回退到初始状态,而是突然还原到原始的红色背景色。在 CSS 中,没有[T0]属性。

然而,我们可以在这两者之间添加额外的步骤。例如,我们可以在更改动画的 50%处将背景颜色设置为绿色。结果可以在以下 URL 中看到:https://codepen.io/AjdinImsirovic/pen/QZWWje

在深入研究 Vue 如何实现转换和动画之前,让我们先看看 CSS 中它们之间的区别。

CSS 中过渡和动画之间的差异

下面是 CSS 中过渡和动画之间的两个快速、不完整的差异列表。

CSS 转换规则

以下是 CSS 转换的一些重要规则:

  • 转换只有隐含的开始和结束状态
  • 执行转换的方式由浏览器决定;换句话说,浏览器决定如何在过渡的两个步骤之间执行转换
  • 我们只能将浏览器指向我们想要转换的确切 CSS 属性,以及持续时间、放松等
  • 转换被触发;t触发器可以是悬停或页面上出现的元素(通过 JavaScript)
  • 转换不能循环
  • 当触发状态(悬停状态)恢复时,即当鼠标未被覆盖时,转换将反向播放
  • 转换语法比动画语法简单

接下来,让我们列出 CSS 动画的重要概念。

CSS 动画的规则

以下是 CSS 动画规则的不完整列表:

  • 动画允许我们指定 CSS 属性的初始状态、中间状态和结束状态
  • 在 CSS 动画中可以有我们需要的任意多个步骤
  • 我们可以延迟动画,播放它们x次(无限次),或者反向播放
  • 动画不必被触发,但它们可以被触发

有了这些基本区别,接下来让我们看看如何在 Vue 中处理过渡和动画。

Vue 中的过渡元素

让我们看看前面的仅 CSS 转换示例,它被移植到 Vue 中。在下面的示例中,第一个按钮包装在自定义组件中,而第二个按钮只是常规的 HTML 按钮元素。它们仍然共享相同的样式,如应用程序的 CSS 中所指定:

<!-- HTML -->
<div id="app">
  <button>Hover me!</button>
  <custom-component></custom-component>
</div>

// JS
Vue.component('customComponent', {
  template: `
    <button>Hover me too!</button>
  `
});
new Vue({
  el: '#app'
});

/* CSS */
button {
  background-color: red;
  transition: background-color 4s;
}
button:hover {
  background-color: blue;
}
/* some additional styling */
* {
  border: none;
  color: white;
  padding: 10px;
  font-size: 18px;
  font-weight: 600;
}

前面的代码可以在这里找到:https://codepen.io/AjdinImsirovic/pen/vVYERO 从示例中可以看出,在本例中,Vue 与转换和动画在纯 HTML 和 CSS 中的工作方式没有差异

Vue 的设计并不是为了覆盖 CSS 转换和动画的正常用例,而是为了配合它们实现一个特定的目标:转换屏幕上的组件的外观和移除。在 Vue 的transition元件的帮助下添加和移除组件。

例如,当您希望一个组件中的事件影响另一个组件的添加和删除时,只需将另一个组件包装在transition元素中。要使用纯 CSS 从前面的示例中构建,下面是 Vue 中的一个简单实现:

<!-- HTML -->
<div id="app">
  <button v-on:click="show = !show">
    Show? {{ show }}
  </button>
  <transition>
    <span v-if="show">
      <custom-component></custom-component>
    </span>
  </transition>
</div>

// JS
Vue.component('customComponent', {
  template: `
    <button>Hover me!</button>
  `
});
new Vue({
  el: '#app',
  data: {
    show: true
  }
});

/* CSS is the same as in the previous example */

示例代码如下:https://codepen.io/AjdinImsirovic/pen/ZqExJO

If you need the element to appear smoothly on the initial page load, without conditions, then you can use the appear attribute on your transition wrapper, like this: <transition appear>.

在前面的代码中,我们根据用户是否单击了第一个按钮,有条件地切换custom-component元素的装载。请注意,原始 CSS 转换在两个按钮中的行为方式仍然完全相同。当我们将鼠标悬停在其中任何一个上方时,我们仍然可以看到背景色从红色到蓝色的四秒钟过渡。当我们离开任何一个按钮时,浏览器仍然会处理按钮背景的反转转换。

但是,在屏幕上安装第二个按钮时没有任何转换。单击第一个按钮后,第二个按钮简单地出现和消失,没有任何放松

为了实现这种逐渐的外观和删除,transition元素带有内置的 CSS 类名。这些内置的转换类名也称为动画挂钩。这些动画挂钩描述包裹在transition元素内的组件的开始状态、结束状态和中间状态;也就是说,它们描述了受影响的组件在屏幕上的开关方式。

我们可以将动画挂钩添加到进入过渡或离开过渡。输入的转换类为v-enterv-enter-activev-enter-to。休假过渡类别为v-leavev-leave-activev-leave-to

设置 enter 转换

在前面的示例的基础上,我们将使用这些动画挂钩使第二个按钮的外观和消失更加平滑。上一个示例与本示例之间的唯一区别是在 CSS 中添加了动画挂钩:

.v-enter {
  opacity: 0;
}
.v-enter-active {
 transition: opacity 3s;
}

此示例的代码可在以下链接中找到:https://codepen.io/AjdinImsirovic/pen/MPWVNm

如果我们将第二个按钮的外观想象为常规 CSS 转换,那么.v-enter动画挂钩将是初始转换状态,.v-enter-active将是中间步骤,.v-enter-to将是最终转换状态,即元素将转换为的内容

因为在我们的示例中没有使用.v-enter-to动画挂钩,所以我们得到的行为如下:当单击第一个按钮时,第二个按钮需要三秒时间将其不透明度从初始值 0 更改为隐含值 1。这就解决了我们的过渡问题。

设置休假过渡

我们前面的示例有一个小问题:当我们再次单击第一个按钮时,第二个按钮将立即消失,因为它的不透明度值将重置为零,而不进行任何转换。原因很简单:我们没有指定任何离开过渡挂钩,所以按钮就消失了。在下一个示例中,我们将通过简单地指定离开转换来解决此问题,如下所示:

.v-leave {
  opacity: 1;
}
.v-leave-active {
  transition: opacity 3s;
}
.v-leave-to {
  opacity: 0;
}

完整代码可在此处找到:https://codepen.io/AjdinImsirovic/pen/XxWqOy 。我们在这段代码中所做的是:当组件需要设置动画时,转换的初始状态是.v-leave.v-leave动画挂钩中的 CSS 声明为opacity: 1。接下来,我们指定中间步骤:要转换的 CSS 属性,即opacity,以及转换的持续时间:3s。最后,我们为转换指定完成状态,其中opacity被设置为零值。

从这些示例中我们可以得出结论,离开过渡的动画挂钩(v-leavev-leave-activev-leave-to应该是*镜像—*比喻性地说,与进入过渡的动画挂钩(v-enterv-enter-activev-enter-to相比)。

我们还可以得出结论,过渡组件及其附带的动画挂钩将用于在屏幕上安装和卸载组件。在屏幕上和屏幕下转换组件时,动画挂钩的自然进程如下:

.v-enter --> .v-enter-active --> .v-enter-to --> .v-leave --> v-leave-active --> .v-leave-to

我们还可以将某些共享相同值的 CSS 选择器分组,如下所示:

.v-enter, .v-leave-to {
  opacity: 0;
}
.v-enter-active, .v-leave-active {
  transition: opacity 3s;
}
.v-enter-to, .v-leave {
  opacity: 1;
}

此示例可在以下网址找到:https://codepen.io/AjdinImsirovic/pen/dgyKMG

从这里可以看出,.v-enter(初始进入动画挂钩)与.v-leave-to(最后离开动画挂钩)的结合正是因为必须反向播放过渡才能获得最期望的行为。类似地,我们正在将中间的步骤,-active钩子分组,以具有相同的transitionCSS 属性。最后,enter 动画的最终钩子需要与初始 leave 动画钩子共享 CSS 声明。此外,由于.v-enter-to.v-leave值在默认情况下是隐含的,我们甚至可以省略它们,并且仍然有一个工作组件转换,类似于官方文档中描述的:中的转换 https://vuejs.org/v2/guide/transitions.html#Transitioning-单元素组件

为了简化推理,在我们最近的示例中,我们还将data选项的show键更改为false的值。这样,最初组件不会装载到 DOM。只有当用户单击第一个按钮时,第二个按钮的 enter 动画挂钩才会生效,并在中平滑过渡组件。再次单击时,第二个按钮的“左”动画挂钩将向内踢,并以相反的方式将组件移出。这一点很重要,因为最初我们有 enter 动画转换,即卸载组件,还有 leave 动画转换,即将组件装载回页面,这可能会使事情变得更加难以解释。

命名转换组件

我们可以给过渡元素赋予name属性。这样做会更改动画挂钩的命名约定。例如,如果我们给我们的转换命名为named,那么动画挂钩需要重命名如下。对于每个转换类,我们将用name属性的值替换开头的v-。因此,v-enter将成为named-enterv-leave将成为named-leave等等。

让我们用命名的转换重写前面的示例:

<!-- HTML -->
<div id="app">
  <button v-on:click="show = !show">
    Show? {{ show }}
  </button>
  <transition name="named">
    <span v-if="show">
      <custom-component></custom-component>
    </span>
  </transition>
</div>

/* CSS */
/* 'named' transition */
.named-enter, .named-leave-to {
  opacity: 0;
}
.named-enter-active, .named-leave-active {
  transition: opacity 3s;
}
.named-enter-to, .named-leave {
  opacity: 1;
}

// JS is unchanged

此示例的代码可在此代码笔中找到:https://codepen.io/AjdinImsirovic/pen/MPWqgm

带有过渡组件的 CSS 动画

CSS 动画也在过渡组件的帮助下使用。这里是前一个 CSS 转换示例的一个示例,使用 CSS 动画转换为。我们将从 HTML 开始:

<div id="app">
  <button v-on:click="show = !show">
    Show? {{ show }}
  </button>
  <transition name="converted">
    <span v-if="show">
      <custom-component></custom-component>
    </span>
  </transition>
</div>

接下来,我们将添加以下 JavaScript 代码:

Vue.component('customComponent', {
  template: `
    <button>Lorem ipsum</button>
  `
});
new Vue({
  el: '#app',
  data: {
    show: false
  }
});

我们还将添加一些简单的样式:

/* 'named' transition is replaced with 'converted' animation */
.converted-enter-active {
  animation: converted .5s;
}
.converted-leave-active {
  animation: converted .5s reverse;
}
@keyframes converted {
  0% { opacity: 0; }
  35% { background-color: purple; }
  65% { background-color: green; }
  100% { opacity: 1; }
}
/* other styles */
button {
  background-color: red;
  transition: background-color 4s;
}
button:hover {
  background-color: blue;
}
/* some additional styling */
* {
  border: none;
  color: white;
  padding: 10px;
  font-size: 18px;
  font-weight: 600;
}
span {
  display: inline-block;
}

此示例的代码在此处可用:https://codepen.io/AjdinImsirovic/pen/vVEXEv 。转换后的动画与前面的 CSS 转换示例完全相同,只是在动画完成 35%和 65%时动画行为发生了变化。我们得到的效果有点像边框颜色效果,尽管我们正在改变这个元素的background-color属性。这证实了我们已经讨论过的一些结论,即:

  • Vue 中的transition元素影响整个<transition>组分的出现和消失,而不是其含量
  • 实际动画可以根据需要有任意多个步骤;换句话说,要获得与 CSS 转换示例中完全相同的效果,只需删除动画完成 35%和 65%时指定的步骤就足够了

在下一节中,我们将讨论自定义转换类。

自定义转换类

当我们想从第三方 CSS 动画库中添加功能时,自定义转换类非常有用。在本例中,我们将使用Animate.CSS动画库,可在此处获得:https://daneden.github.io/animate.css/

官方文档充分说明了自定义转换类在以下 URL 中的使用:https://vuejs.org/v2/guide/transitions.html#Custom-过渡类

唯一需要补充的是我们一直在构建的示例,可在此处获得:https://codepen.io/AjdinImsirovic/pen/rqazXZ

该示例的代码如下所示。首先,我们将从 HTML 开始:

<div id="app">
  <button v-on:click="show = !show">
    Show? {{ show }}
  </button>
  <transition :duration="4000"
     name="converted"
     enter-active-class="rubberBand animated"
     leave-active-class="bounceOut animated">
        <div v-if="show">
          <custom-component>
          </custom-component>
        </div>
  </transition>
</div>

接下来,让我们看看 JavaScript:

Vue.component('customComponent', {
  template: `
    <button>Lorem ipsum</button>
  `
});
new Vue({
  el: '#app',
  data: {
    show: false
  }
});

最后,在我们的样式中,我们将设置一些基本的 CSS 声明:

button {
  background-color: red;
  transition: background-color 4s;
}
button:hover {
  background-color: blue;
}

* {
  border: none;
  color: white;
  padding: 10px;
  font-size: 18px;
  font-weight: 600;
}
* { overflow: hidden }

基本上,我们指定与动画挂钩具有相同名称的属性,加上属性名称末尾的附加-class。因此,默认的v-enter-activeCSS 类成为自定义的enter-active-classHTML 属性。然后,我们给这个自定义 HTML 属性一个我们选择的值。我们给它的值是我们想要从 CSS 动画库中使用的效果的类名,我们之前在本例中选择了Animate.CSS库。在前面的代码中,我们还设置了:duration属性,将转换的持续时间精确地指定为 4000 毫秒。实际上,在我们的示例中,只有当我们设置的:duration属性比我们从第三方库提供的动画持续时间短时,这才会产生效果。例如,尝试将[T6]属性设置为 100 毫秒,然后看到动画被截断。这可以产生一些有趣的效果。

组合过渡模式、持续时间、关键点和 v-if

当我们希望平滑地从屏幕上删除一个元素并无缝地将其替换为另一个元素时,可以使用转换模式。<transition>组件附带的默认转换模式(无需任何调整)是同时转换:在添加另一个元素的同时删除一个元素

然而,有一些转换是最好让新元素出现的,并且只有当这个转换完成时旧元素才会被删除。该过渡模式称为in-out过渡模式。要添加它,我们只需使用 custom mode HTML 属性,并将其值设置为in-out,如下所示:

<transition mode="in-out">

或者,我们可能希望使用out-in转换模式,首先将旧元素转换为 out,然后在转换完成后,将新元素转换为 in。

让我们在实践中看到这一点。该笔提供了示例:https://codepen.io/AjdinImsirovic/pen/yRyPed

以下是 HTML:

<div id="app">
  <transition name="smooth" mode="out-in" :duration="500">
      <button v-if="show" 
              key="first" 
              v-on:click="show = !show">
                Show? {{ show }}
      </button>
      <button v-else
              key="second" 
              v-on:click="show = !show">
                Show? {{ show }}
      </button> 
  </transition>
  <transition :duration="1000"
     enter-active-class="slideInDown animated"
     leave-active-class="slideOutDown animated">
        <div v-if="show">
          <custom-component>
          </custom-component>
        </div>
  </transition>
</div>

我们仍在使用相同的 JS:

Vue.component('customComponent', {
  template: `
    <button>Lorem ipsum</button>
  `
});
new Vue({
  el: '#app',
  data: {
    show: false
  }
});

我们的 CSS 有一些变化:

/* CSS classes used are imported from the Animate CSS library
and can be found in Settings of this pen */
/* other styles */
.smooth-enter, .smooth-leave-to {
  opacity: 0;
}
.smooth-enter-active, .smooth-leave-active {
  transition: opacity .5s;
}
.smooth-enter-to, .smooth-leave {
  opacity: 1;
}

button {
  background-color: red;
  transition: background-color 4s;
}
button:hover {
  background-color: blue;
}

* {
  border: none;
  color: white;
  padding: 10px;
  font-size: 18px;
  font-weight: 600;
}
* { overflow: hidden }

我们在转换中的两个button元素之间切换。由于这两个具有相同的标记名,我们需要为它们提供不同的key属性,以便 Vue 能够区分它们。

此外,我们正在有条件地呈现按钮。当我们在第一个按钮中保持对v-if="show"的检查时,在第二个按钮中,我们只是使用v-else指令,而没有给它一个要检查的值。

在 Vue 中绑定 CSS 样式

在本节中,我们将讨论如何在安装或删除组件时设置页面其他部分的动画。为此,我们将使用v-bind指令,如前几章所述,我们可以使用该指令绑定 HTML 属性。一旦绑定,这些属性就可以从我们的 Vue 实例进行操作。

我们将演示一个简单的 CSS 绑定样式示例。就网页可用性而言,入职是向 web 应用程序的新用户展示网页所具有的整体功能的实践,这是通过突出显示网页的某一部分并显示带有一些信息的 popover 来实现的,这些信息进一步描述了入职过程中特定步骤的功能。

首先,我们需要了解,我们可以通过将[T0]指令的值作为对象传递来静态绑定 CSS 类,如下例所示:

<p v-bind:class="{}">Some text...</p>

在对象内部,我们可以简单地添加 CSS 类作为键,布尔值[T0]和[T1]作为值。将使用设置为true的 CSS 值,否则不会使用,如以下示例所示:

<button v-bind:class="{'btn': true, 'btn-lg': true, 'btn-primary': true, 'btn-secondary': false}">A button</button>

在本例中,我们使用的是引导框架的 CSS 类。我们将按钮设置为btn-primary类,因为它被设置为true,而不是btn-secondary,后者被设置为 false

因为v-bind指令允许我们以编程方式控制 HTML 属性,我们可以让我们的应用程序在点击后切换 CSS 类。例如,在基本 Vue 应用程序中,我们可以在 HTML 中执行此操作:

<button v-bind:class="'btn':true','btn-lg':true, 'btn-primary':true, 'btn-secondary':btnClicked">
A button
</button>

在前面的代码中,我们将btnbtn-lgbtn-primary的类设置为true,并将btn-secondary的值设置为btnClicked。接下来,我们将在 JavaScript 中将btnClicked的值设置为false

data: {
  btnClicked: false,
}

最后,我们将把点击事件添加到我们的按钮中,因此当点击时,btnClicked的值将从true切换到false,反之亦然。代码如下:

<button 
  v-on:click="btnClicked = !btnClicked" 
  v-bind:class="'btn':true','btn-lg':true, 'btn-primary':true, 'btn-secondary':btnClicked">
    A button
</button>

此示例可从以下 URL 获得:https://codepen.io/AjdinImsirovic/pen/KGVvML

我们可以通过使用data属性来存储 CSS 类组,并使用 JavaScript 三元表达式来检查btnClicked值当前是否设置为truefalse来进一步扩展此示例:

<!-- HTML -->
<div id="app" class="p-4">
  <h1>Improving dynamic CSS classes example</h1>
  <p class="lead">Click the button below a few times</p>
  <button 
    v-on:click="btnClicked = !btnClicked" 
    v-bind:class="btnClicked ? btnPrimary : btnSecondary">
      btnClicked {{ btnClicked }} 
  </button>
</div>

// JS
new Vue({
  el: '#app',
  data() {
    return {
      btnClicked: false,
      btnPrimary: 'btn btn-lg btn-primary',
      btnSecondary: 'btn btn-lg btn-secondary'
    }
  }
})

上一示例的代码可在中找到 https://codepen.io/AjdinImsirovic/pen/wYMEJQ

使用动态 CSS 类设置单击按钮的动画

现在,我们只需从前面提到的 Animate.CSS 动画库中添加额外的 CSS 类,就可以添加动画了。对上一个示例代码的更新非常少。我们在这里只添加了两个 CSS 类:

      btnPrimary: 'btn btn-lg btn-primary bounce animated',

当然,我们还必须包括 Animate.CSS 库,如图所示:https://codepen.io/AjdinImsirovic/pen/RerEyy 。要在两次单击中添加动画,我们只需将btnSecondary的条目更改为:

btnSecondary: 'btn btn-lg btn-secondary tada animated'

现在,按钮将在每次单击时设置动画。

与过渡小组合作

当单个过渡组件用于环绕单个元素时,过渡组用于设置多个元素的动画。它们附带了一个额外的动画挂钩:v-move

在下面的示例中,我们将构建一个简单的功能,用户可以在线奖励一段内容,并使用掌声*、这一概念类似于的鼓掌功能 https://medium.com/ ,其工作原理如下:如果网站访问者喜欢某个内容,他们可以通过点击“鼓掌”按钮多达 50 次,以鼓掌*的方式奖励它。因此,claps 功能就像一个计数器,显示网站访问者对内容的欣赏程度。

在我们的实现中,我们将结合已经介绍过的功能。区别在于,我们将使用transition-group组件,而不是转换。这是 HTML 代码:

<!-- HTML -->
<div id="app">
    <div class="tale">
        <transition-group>
          <button 
                  class="bare" 
                  key="howManyClaps" 
                  v-if="clapCount">
                    {{ clapCount }}
          </button>
          <button 
                  class="fa fa-thumbs-o-up animated orange" 
                  key="theClapButton" 
                  v-on:click="aClap()">
          </button>
        </transition-group>
    </div>
</div>

以下是 JS 代码:

new Vue({
  el: "#app",
  data: { 
    clapCount: false
  },
  methods: {
    aClap() {
      var target = document.querySelector('.fa-thumbs-o-up');
      if (!target.classList.contains('wobble')) {
        target.classList.add('wobble');
      }
      setTimeout(function() {
        target.classList.remove('wobble')}, 300
      )
      if (this.clapCount < 10) {
        this.clapCount++
      } else {
        target.classList.remove('orange','wobble')
      }
    }
  }
});

下面是 CSS 代码:

button.bare {
  font-size: 30px;
  background: white;
  border: none;
  margin: 0 20px;
}
button:focus.bare, button:focus.fa {
  outline: 0;
}
button.fa {
  cursor: pointer;
  color: white;
  padding: 20px;
  border-radius: 50%;
  font-size: 30px;
  border: none;
}
.orange {
  background: orange;
}

/* animation hooks */
.v-enter,
.v-leave-to{
  opacity: 0;
  transform: translate(1000px, 500px);
}
.v-enter-active,
.v-leave-active {
  transition: opacity 5s, transform 1s
}

前面的代码在此 URL以钢笔的形式提供 https://codepen.io/AjdinImsirovic/pen/JmXJgd

这段代码中发生了几件事。在 HTML 中,我们使用transition-group组件处理两个按钮。在 JS 中,我们为拍子的行为设置了逻辑。我们开始将clapCount设置为false,强制为零。在 CSS 中,我们为按钮设置样式,并使用动画挂钩。transformtransition值已设置为极值,以便能够更好地了解它们的工作原理,方法是使用这些值(例如,X轴上的1000 px平移,以及Y轴上的500 px平移)。

JavaScript 动画挂钩

我们可以使用 Vue 的transition类作为 JavaScript 方法。就像生命周期挂钩一样,我们不必访问它们中的任何一个。或者我们可以挑选那些我们想用的。首先,在我们的 Vue 构造函数的methods选项中,我们可以指定如何处理它们:

  methods: {
    // ENTER transitions...
    beforeEnter: function(el) {},
    enter: function(el, done) {},
    afterEnter: function(el) {},
    enterCancelled: function(el) {},
    // LEAVE transitions...
    beforeLeave: function(el) {},
    leave: function(el,done) {},
    afterLeave: function(el) {},
    leaveCancelled: function(el) {},
  }

正如我们所看到的,我们有四种方法用于进入转换,另外四种方法用于离开转换。所有方法都采用了el参数,enterleave方法也采用了done参数来表示动画的完成。如果没有使用[T4]参数,那么将调用钩子而不等待[T5]回调完成,并且转换将立即完成。

让我们使用这些 JavaScript 动画挂钩重写前面的示例。为了让事情更容易理解,我们将把官方文档的示例集成到我们的示例中,这样我们就可以看到当仅通过 JavaScript 调用动画挂钩时,这个示例是如何工作的

这是我们将在 HTML 中使用的代码:

<transition 
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:leave="leave"
  v-bind:css="false">
<p v-if="show" style="font-size:25px">Animation example with velocity</p>
</transition>

这是我们将在 JS 中使用的代码:

new Vue({
  el: "#app",
  data: { 
    clapCount: false
  },
  methods: {
    beforeEnter: function(el) {
      el.style.opacity = 0
    },
        enter: function (el, done) {
      Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
      Velocity(el, { fontSize: '1em' }, { complete: done })
    },
    leave: function (el, done) {
      Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { 
      duration: 600 })
      Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
      Velocity(el, {
        rotateZ: '45deg',
        translateY: '30px',
        translateX: '30px',
        opacity: 0
      }, { complete: done })},
    aClap() {
      var target = document.querySelector('.fa-thumbs-o-up');
      if (!target.classList.contains('wobble')) {
        target.classList.add('wobble');
      }
      setTimeout(function() {
        target.classList.remove('wobble')}, 300
      )
      if (this.clapCount < 10) {
        this.clapCount++
      } else {
        target.classList.remove('orange','wobble')
      }
    }
  }
});

以下是 CSS:

button.bare {
  font-size: 30px;
  background: white;
  border: none;
  margin: 0 20px;
}
button:focus.bare, button:focus.fa {
  outline: 0;
}
button.fa {
  cursor: pointer;
  color: white;
  padding: 20px;
  border-radius: 50%;
  font-size: 30px;
  border: none;
}
.orange {
  background: orange;
}

此处提供了示例:https://codepen.io/AjdinImsirovic/pen/PyzqxM

有了这种理解,就可以很容易地更改 Vue 构造函数中特定方法中的参数,以实现 JavaScript 驱动的动画所需的效果。

总结

在本章中,我们介绍了如何在 Vue.js 中使用过渡和动画。具体来说,我们研究了过渡和动画如何在 CSS 中工作。我们研究了 CSS 中过渡和动画之间的差异,并为两者建立了规则。我们在 Vue 中使用了 transition 和 transition group 元素,并讨论了动画挂钩及其在进入和离开过渡中的分组。我们了解了如何命名和指定转换组件,以及如何指定自定义转换类,以便更容易地与第三方动画库集成。

我们解释了何时使用过渡模式以及如何使用[T0]和[T1]指令进一步调整动画。我们提到了在 Vue 中绑定 CSS 样式的重要性,以及如何使用这种方法向 web 应用程序添加动画。最后,我们了解了如何将基于 CSS 类的转换转换为基于 JavaScript 的动画挂钩。

在下一章中,我们将讨论如何使用 Vuex。