Menu
×
   ❮   
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP HOW TO W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

Vue <Transition> 组件


示例

使用内置的 <Transition> 组件来动画一个 <p> 元素,当它使用 v-if 移除时。

<Transition>
  <p v-if="exists">Hello World!</p>
</Transition>
运行示例 »

请查看以下更多示例。


定义和使用

内置的 <Transition> 组件用于在使用 v-ifv-show 或动态组件添加或移除元素时对其进行动画处理。

元素动画规则写在自动生成的类或 JavaScript 转场钩子中。请查看下面的表格。

<Transition> 组件的根级别只能有一个元素。


Props

Prop 描述
none 默认值。 运行示例 »
appear 如果设置为 true,元素在首次挂载时也会被动画处理。默认值为 false 运行示例 »
mode mode="out-in" 确保初始元素在下一个元素进入之前离开。 mode="in-out" 确保新元素在旧元素离开之前进入。默认情况下,旧元素与新元素同时离开。 运行示例 »
name 指定转场的名称。如果有多个转场,我们需要为它们指定唯一的名称来区分它们。 name="swirl" 确保 CSS 转场类以 swirl- 开头,而不是默认前缀 v- 运行示例 »
css 布尔值。 :css="false" 告诉 Vue 编译器此转场不使用任何转场类,只使用 JavaScript 钩子。设置此 prop 后,必须在 enter 和 leave 钩子中使用 done() 回调。 运行示例 »
type 指定是等待 'animation' 还是 'transition' 来完成转场。如果同时设置了 CSS 动画和 CSS 转场,并且未设置此 type prop,Vue 会检测这两个中的最长持续时间并将其用作转场时间。
duration 指定 'enter' 和 'leave' 的转场时间长度。默认情况下,在 CSS 动画或 CSS 转场结束时结束。可以像这样定义特定的时间 :duration="{enter:2000, leave:1000 }",或者像这样 duration="1000"
enterFromClass
enterActiveClass
enterToClass
appearFromClass
appearActiveClass
appearToClass
leaveFromClass
leaveActiveClass
leaveToClass
使用这些 props 来重命名转场类。

像这样使用其中一个 props enter-active-class="entering" 表示该转场类在 CSS 中可以被引用为 .entering,而不是默认的 .v-enter-active。约定是在模板中使用 kebab-case 来表示 props,这与 HTML 中属性的编写方式一致。

运行示例 »

CSS 转场类

当我们使用 <Transition> 组件时,我们自动获得六个不同的 CSS 类,这些类可以用来在元素添加或移除时对其进行动画处理。

这些类在元素添加 (enter) 或移除 (leave) 时的不同阶段处于活动状态

转场类 描述
v-enter-from 进入阶段开始时元素的初始样式 运行示例 »
v-enter-active 元素在进入阶段期间的样式 运行示例 »
v-enter-to 元素在进入阶段结束时的样式 运行示例 »
v-leave-from 离开阶段开始时元素的初始样式 运行示例 »
v-leave-active 元素在离开阶段期间的样式 运行示例 »
v-leave-to 元素在离开阶段结束时的样式 运行示例 »

JavaScript 转场钩子

上面的转场类对应于我们可以钩入以运行 JavaScript 代码的事件。

JavaScript 事件 描述
before-enter 在进入阶段开始时调用
enter 在 'before-enter' 钩子之后,在进入阶段期间调用 运行示例 »
after-enter 在进入转场结束时调用 运行示例 »
enter-cancelled 如果进入转场被取消,则调用 运行示例 »
before-leave 在离开阶段开始时调用 运行示例 »
leave 在 'before-leave' 钩子之后,在离开阶段期间调用 运行示例 »
after-leave 在离开转场结束时调用
leave-cancelled 仅当使用 v-show 并且离开阶段被取消时调用

更多示例

示例 1

一个 <p> 元素在切换时滑入滑出。

<template>
  <h1>Add/Remove <p> Tag</h1>
  <button @click="this.exists = !this.exists">{{btnText}}</button><br>
  <Transition>
    <p v-if="exists">Hello World!</p>
  </Transition>
</template>

<script>
export default {
  data() {
    return {
      exists: false
    }
  },
  computed: {
    btnText() {
      if(this.exists) {
        return 'Remove';
      }
      else {
        return 'Add';
      }
    }
  }
}
</script>

<style>
  .v-enter-from {
    opacity: 0;
    translate: -100px 0;
  }
  .v-enter-to {
    opacity: 1;
    translate: 0 0;
  }
  .v-leave-from {
    opacity: 1;
    translate: 0 0;
  }
  .v-leave-to {
    opacity: 0;
    translate: 100px 0;
  }
  p {
    background-color: lightgreen;
    display: inline-block;
    padding: 10px;
    transition: all 0.5s;
  }
</style>
运行示例 »

示例 2

一个 <p> 元素在 'enter' 和 'leave' 期间具有不同的背景颜色

<template>
  <h1>Add/Remove <p> Tag</h1>
  <button @click="this.exists = !this.exists">{{btnText}}</button><br>
  <Transition>
    <p v-if="exists">Hello World!</p>
  </Transition>
</template>

<script>
export default {
  data() {
    return {
      exists: false
    }
  },
  computed: {
    btnText() {
      if(this.exists) {
        return 'Remove';
      }
      else {
        return 'Add';
      }
    }
  }
}
</script>

<style>
  .v-enter-active {
    background-color: lightgreen;
    animation: added 1s;
  }
  .v-leave-active {
    background-color: lightcoral;
    animation: added 1s reverse;
  }
  @keyframes added {
    from {
      opacity: 0;
      translate: -100px 0;
    }
    to {
      opacity: 1;
      translate: 0 0;
    }
  }
  p {
    display: inline-block;
    padding: 10px;
    border: dashed black 1px;
  }
</style>
运行示例 »

示例 3

<p> 元素使用 name prop 来区分 <Transition> 组件,因此动画效果不同。

<template>
  <h1>Add/Remove <p> Tag</h1>
  <p>The second transition in this example has the name prop "swirl", so that we can keep the transitions apart with different class names.</p>
  <hr>
  <button @click="this.p1Exists = !this.p1Exists">{{btn1Text}}</button><br>
  <Transition>
    <p v-if="p1Exists" id="p1">Hello World!</p>
  </Transition>
  <hr>
  <button @click="this.p2Exists = !this.p2Exists">{{btn2Text}}</button><br>
  <Transition name="swirl">
    <p v-if="p2Exists" id="p2">Hello World!</p>
  </Transition>
</template>

<script>
export default {
  data() {
    return {
      p1Exists: false,
      p2Exists: false
    }
  },
  computed: {
    btn1Text() {
      if(this.p1Exists) {
        return 'Remove';
      }
      else {
        return 'Add';
      }
    },
    btn2Text() {
      if(this.p2Exists) {
        return 'Remove';
      }
      else {
        return 'Add';
      }
    }
  }
}
</script>

<style>
  .v-enter-active {
    background-color: lightgreen;
    animation: added 1s;
  }
  .v-leave-active {
    background-color: lightcoral;
    animation: added 1s reverse;
  }
  @keyframes added {
    from {
      opacity: 0;
      translate: -100px 0;
    }
    to {
      opacity: 1;
      translate: 0 0;
    }
  }
  .swirl-enter-active {
    animation: swirlAdded 1s;
  }
  .swirl-leave-active {
    animation: swirlAdded 1s reverse;
  }
  @keyframes swirlAdded {
    from {
      opacity: 0;
      rotate: 0;
      scale: 0.1;
    }
    to {
      opacity: 1;
      rotate: 360deg;
      scale: 1;
    }
  }
  #p1, #p2 {
    display: inline-block;
    padding: 10px;
    border: dashed black 1px;
  }
  #p2 {
    background-color: lightcoral;
  }
</style>
运行示例 »

示例 4

after-enter 事件触发一个 <div> 元素的显示。

<template>
  <h1>JavaScript Transition Hooks</h1>
  <p>This code hooks into "after-enter" so that after the initial animation is done, a method runs that displays a red div.</p>
  <button @click="pVisible=true">Create p-tag!</button><br>
  <Transition @after-enter="onAfterEnter">
    <p v-show="pVisible" id="p1">Hello World!</p>
  </Transition>
  <br>
  <div v-show="divVisible">This appears after the "enter-active" phase of the transition.</div>
</template>

<script>
export default {
  data() {
    return {
      pVisible: false,
      divVisible: false
    }
  },
  methods: {
    onAfterEnter() {
      this.divVisible = true;
    }
  }
}
</script>

<style>
  .v-enter-active {
    animation: swirlAdded 1s;
  }
  @keyframes swirlAdded {
    from {
      opacity: 0;
      rotate: 0;
      scale: 0.1;
    }
    to {
      opacity: 1;
      rotate: 360deg;
      scale: 1;
    }
  }
  #p1, div {
    display: inline-block;
    padding: 10px;
    border: dashed black 1px;
  }
  #p1 {
    background-color: lightgreen;
  }
  div {
    background-color: lightcoral;
  }
</style>
运行示例 »

示例 5

一个切换按钮触发 enter-cancelled 事件。

<template>
  <h1>The 'enter-cancelled' Event</h1>
  <p>Click the toggle button again before the enter animation is finished to trigger the 'enter-cancelled' event.</p>
  <button @click="pVisible=!pVisible">Toggle</button><br>
  <Transition @enter-cancelled="onEnterCancelled">
    <p v-if="pVisible" id="p1">Hello World!</p>
  </Transition>
  <br>
  <div v-if="divVisible">You interrupted the "enter-active" transition.</div>
</template>

<script>
export default {
  data() {
    return {
      pVisible: false,
      divVisible: false
    }
  },
  methods: {
    onEnterCancelled() {
      this.divVisible = true;
    }
  }
}
</script>

<style>
  .v-enter-active {
    animation: swirlAdded 2s;
  }
  @keyframes swirlAdded {
    from {
      opacity: 0;
      rotate: 0;
      scale: 0.1;
    }
    to {
      opacity: 1;
      rotate: 720deg;
      scale: 1;
    }
  }
  #p1, div {
    display: inline-block;
    padding: 10px;
    border: dashed black 1px;
  }
  #p1 {
    background-color: lightgreen;
  }
  div {
    background-color: lightcoral;
  }
</style>
运行示例 »

示例 6

appear prop 在页面加载后立即开始 <p> 元素动画。

<template>
  <h1>The 'appear' Prop</h1>
  <p>The 'appear' prop starts the animation when the p tag below is rendered for the first time as the page opens. Without the 'appear' prop, this example would have had no animation.</p>
  <Transition appear>
    <p id="p1">Hello World!</p>
  </Transition>
</template>

<style>
  .v-enter-active {
    animation: swirlAdded 1s;
  }
  @keyframes swirlAdded {
    from {
      opacity: 0;
      rotate: 0;
      scale: 0.1;
    }
    to {
      opacity: 1;
      rotate: 360deg;
      scale: 1;
    }
  }
  #p1 {
    display: inline-block;
    padding: 10px;
    border: dashed black 1px;
    background-color: lightgreen;
  }
</style>
运行示例 »

示例 7

在 'enter' 和 'leave' 上使用动画翻阅图像。新图像在旧图像移除之前添加。

<template>
  <h1>Transition Between Elements</h1>
  <p>Click the button to get a new image.</p>
  <p>The new image is added before the previous is removed. We will fix this in the next example with mode="out-in".</p>
  <button @click="newImg">Next image</button><br>
  <Transition>
    <img src="/img_pizza.svg" v-if="imgActive === 'pizza'">
    <img src="/img_apple.svg" v-else-if="imgActive === 'apple'">
    <img src="/img_cake.svg" v-else-if="imgActive === 'cake'">
    <img src="/img_fish.svg" v-else-if="imgActive === 'fish'">
    <img src="/img_rice.svg" v-else-if="imgActive === 'rice'">
  </Transition>
</template>

<script>
export default {
  data() {
    return {
      imgActive: 'pizza',
      imgs: ['pizza', 'apple', 'cake', 'fish', 'rice'],
      indexNbr: 0
    }
  },
  methods: {
    newImg() {
      this.indexNbr++;
      if(this.indexNbr >= this.imgs.length) {
        this.indexNbr = 0;
      }
      this.imgActive = this.imgs[this.indexNbr];
    }
  }
}
</script>

<style>
  .v-enter-active {
    animation: swirlAdded 1s;
  }
  .v-leave-active {
    animation: swirlAdded 1s reverse;
  }
  @keyframes swirlAdded {
    from {
      opacity: 0;
      rotate: 0;
      scale: 0.1;
    }
    to {
      opacity: 1;
      rotate: 360deg;
      scale: 1;
    }
  }
  img {
    width: 100px;
    margin: 20px;
  }
  img:hover {
    cursor: pointer;
  }
</style>
运行示例 »

示例 8

在 'enter' 和 'leave' 上使用动画翻阅图像。 mode="out-in" 阻止新图像在旧图像移除之前添加。

<template>
  <h1>mode="out-in"</h1>
  <p>Click the button to get a new image.</p>
  <p>With mode="out-in", the next image is not added until the current image is removed. Another difference from the previous example, is that here we use computed prop instead of a method.</p>
  <button @click="indexNbr++">Next image</button><br>
  <Transition mode="out-in">
    <img src="/img_pizza.svg" v-if="imgActive === 'pizza'">
    <img src="/img_apple.svg" v-else-if="imgActive === 'apple'">
    <img src="/img_cake.svg" v-else-if="imgActive === 'cake'">
    <img src="/img_fish.svg" v-else-if="imgActive === 'fish'">
    <img src="/img_rice.svg" v-else-if="imgActive === 'rice'">
  </Transition>
</template>

<script>
export default {
  data() {
    return {
      imgs: ['pizza', 'apple', 'cake', 'fish', 'rice'],
      indexNbr: 0
    }
  },
  computed: {
    imgActive() {
      if(this.indexNbr >= this.imgs.length) {
        this.indexNbr = 0;
      }
      return this.imgs[this.indexNbr];
    }
  }
}
</script>

<style>
  .v-enter-active {
    animation: swirlAdded 0.7s;
  }
  .v-leave-active {
    animation: swirlAdded 0.7s reverse;
  }
  @keyframes swirlAdded {
    from {
      opacity: 0;
      rotate: 0;
      scale: 0.1;
    }
    to {
      opacity: 1;
      rotate: 360deg;
      scale: 1;
    }
  }
  img {
    width: 100px;
    margin: 20px;
  }
  img:hover {
    cursor: pointer;
  }
</style>
运行示例 »

示例 9

在组件之间切换时使用动画。

<template>
  <h1>Transition with Dynamic Components</h1>
  <p>The Transition component wraps around the dynamic component so that the switching can be animated.</p>
  <button @click="toggleValue = !toggleValue">Switch component</button>
  <Transition mode="out-in">
    <component :is="activeComp"></component>
  </Transition>
</template>

<script>
  export default {
    data () {
      return {
        toggleValue: true
      }
    },
    computed: {
      activeComp() {
        if(this.toggleValue) {
          return 'comp-one'
        }
        else {
          return 'comp-two'
        }
      }
    }
  }
</script>

<style>
  .v-enter-active {
    animation: slideIn 0.5s;
  }
  @keyframes slideIn {
    from {
      translate: -200px 0;
      opacity: 0;
    }
    to {
      translate: 0 0;
      opacity: 1;
    }
  }
  .v-leave-active {
    animation: slideOut 0.5s;
  }
  @keyframes slideOut {
    from {
      translate: 0 0;
      opacity: 1;
    }
    to {
      translate: 200px 0;
      opacity: 0;
    }
  }
  #app {
    width: 350px;
    margin: 10px;
  }
  #app > div {
    border: solid black 2px;
    padding: 10px;
    margin-top: 10px;
  }
</style>
运行示例 »

示例 10

在组件之间切换时使用动画。

<template>
  <h1>The :css="false" Prop</h1>
  <p>With the 'css' prop set to 'false', we tell the compiler that JavaScript hooks are used instead of CSS transition classes.</p>
  <p>When we use :css="false", we must call done() inside the 'enter' and the 'leave' hooks, to tell the browser when those transitions are finished.</p>
  <button @click="pVisible=!pVisible">Toggle</button>
  <div>
    <Transition
      :css="false" 
      @enter="onEnter"
      @after-enter="onAfterEnter"
      @before-leave="onBeforeLeave"
      @leave="onLeave"
    >
      <p 
        v-if="pVisible"
        id="p1">
        Hello World!
      </p>
    </Transition>
  </div>
</template>

<script>
export default {
  data() {
    return {
      pVisible: false
    }
  },
  methods: {
    onEnter(el,done) {
      let pos = 0;
      window.requestAnimationFrame(frame);
      function frame() {
        if (pos > 150) {
          done();
        } else {
          pos++; 
          el.style.left = pos + "px"; 
          window.requestAnimationFrame(frame);
        }
      }
    },
    onAfterEnter(el) {
      el.style.backgroundColor = "yellow";
    },
    onBeforeLeave(el) {
      el.style.backgroundColor = "lightgreen";
    },
    onLeave(el,done) {
      let pos = 150;
      window.requestAnimationFrame(frame);
      function frame() {
        if (pos < 0) {
          done();
        }
        else {
          pos--;
          el.style.left = pos + "px"; 
          window.requestAnimationFrame(frame);
        }
      }
    }
  }
}
</script>

<style>
  #p1 {
    position: absolute;
    padding: 10px;
    border: dashed black 1px;
    background-color: lightgreen;
  }
  #app > div {
    position: relative;
    background-color: coral;
    width: 300px;
    height: 300px;
    border: dashed black 1px;
    margin-top: 20px;
  }
</style>
运行示例 »

示例 11

使用 enterActiveClass prop 将 'v-enter-active' CSS 类重命名为 'entering'。

<template>
  <h1>The 'enterActiveClass' Prop</h1>
  <button @click="this.exists = !this.exists">{{btnText}}</button><br>
  <Transition enter-active-class="entering">
    <p v-if="exists">Hello World!</p>
  </Transition>
</template>

<script>
export default {
  data() {
    return {
      exists: false
    }
  },
  computed: {
    btnText() {
      if(this.exists) {
        return 'Remove';
      }
      else {
        return 'Add';
      }
    }
  }
}
</script>

<style>
  .entering {
    background-color: lightgreen;
    animation: added 1s;
  }
  .v-leave-active {
    background-color: lightcoral;
    animation: added 1s reverse;
  }
  @keyframes added {
    from {
      opacity: 0;
      translate: -100px 0;
    }
    to {
      opacity: 1;
      translate: 0 0;
    }
  }
  p {
    display: inline-block;
    padding: 10px;
    border: dashed black 1px;
  }
</style>
运行示例 »

相关页面

Vue 教程:Vue 动画

Vue 教程:Vue 动画与 v-for

Vue 参考:Vue <TransitionGroup> 组件


×

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail:
[email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail:
[email protected]

W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.

Copyright 1999-2024 by Refsnes Data. All Rights Reserved. W3Schools is Powered by W3.CSS.