Entrée/Quitter et Liste des Transitions


Table des matières

Transition CSS

  • CSS Animation

  • Nom de classe de transition personnalisé

    • Utiliser la transition et l'animation en même temps

    • Durée de transition explicite

    • Hook JavaScript

    • Transition pour le rendu initial

    • Transition pour plusieurs éléments

    • Mode de transition

    • Transition pour plusieurs composants
  • Liste transition

  • Entrée/ laisser les transitions pour les listes

    • Trier les transitions pour les listes

  • Transitions échelonnées pour les listes

  • Transitions réutilisables

    • Transition dynamique

    • Vue d'ensemble

    Vue propose de nombreuses façons différentes d'appliquer des effets de transition lors de l'insertion, de la mise à jour ou de la suppression de DOM.
  • Comprend les outils suivants :

  • Appliquer automatiquement les classes dans les transitions et les animations CSS
  • Peut être utilisé avec des bibliothèques d'animation CSS tierces, telles que Animate.css

Utiliser JavaScript directement dans le hook de transition les fonctions DOM

peuvent être utilisées avec des bibliothèques d'animation JavaScript tierces, telles que Velocity.js

Ici, nous ne parlerons que de la transition d'entrée, de sortie et de liste, vous pouvez également consulter la section suivante
Gérer l'état de transition

.

  • Transition d'un seul élément/composant

  • Vue fournit le composant package de transition Dans les situations suivantes, vous pouvez ajouter une transition d'entrée/sortie à n'importe quel élément ou composant.
  • Rendu conditionnel (en utilisant v-if)
  • Affichage conditionnel (en utilisant v-show)

Composant dynamique


Racine du composant nœud

Voici un exemple typique :

<div id="demo">
  <button v-on:click="show = !show">
    Toggle
  </button>
  <transition name="fade">
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({
  el: '#demo',
  data: {
    show: true
  }
})
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}

3.gif

Lors de l'insertion ou de la suppression d'éléments contenus dans le composant transition, Vue fera ce qui suit : transition 组件中的元素时,Vue 将会做以下处理:

 1. 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。

 2. 如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。

 3. 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)


过渡的类名

在进入/离开的过渡中,会有 6 个 class 切换。

 1.  v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

 2.  v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

 3.  v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

 4. v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

 5.  v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

 6.  v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

1.png

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

 1. Reniflage automatique Si l'élément cible a Transitions ou animations CSS appliquées, et si tel est le cas, ajoutez/supprimez les noms de classes CSS au moment approprié. 🎜🎜 2. Si le composant de transition fournit des fonctions de hook JavaScript, ces fonctions de hook seront exécutées de manière appropriée Le timing est appelé. 🎜🎜 3. Si aucun hook JavaScript n'est trouvé et qu'aucune transition/animation CSS n'est détectée, les opérations DOM (insertion/suppression) sont effectuées immédiatement dans l'image suivante. (Remarque : cela fait référence au mécanisme d'animation image par image du navigateur, qui est différent du concept nextTick de Vue)🎜🎜
🎜

Nom de la classe de transition🎜🎜Pendant la transition entrée/sortie, il y aura 6 changements de classe. 🎜🎜 1. v-enter : Définissez l'état de départ pour entrer dans la transition. Il prend effet avant l'insertion de l'élément et est supprimé à l'image suivante après l'insertion de l'élément. 🎜🎜 2. v-enter-active : Définissez l'état dans lequel la transition d'entrée prend effet. S'applique tout au long de la transition, prend effet avant l'insertion de l'élément et est supprimé une fois la transition/animation terminée. Cette classe peut être utilisée pour définir des temps de processus, des retards et des fonctions de courbe pour la saisie des transitions. 🎜🎜 3. v-enter-to : Version 2.1.8 et supérieure Définit l'état final de la transition d'entrée. Prend effet à l'image suivante après l'insertion de l'élément (en même temps que v-enter est supprimé) et est supprimé une fois la transition/animation terminée. 🎜🎜 4. v-leave : Définissez l'état de départ de la transition de congé. Il prend effet immédiatement lorsque la transition de sortie est déclenchée et est supprimé à l'image suivante. 🎜🎜 5. v-leave-active : Définissez l'état dans lequel la transition de congé prend effet. S'applique tout au long de la transition de sortie, prend effet immédiatement lorsque la transition de sortie est déclenchée et est supprimé une fois la transition/animation terminée. Cette classe peut être utilisée pour définir des temps de processus, des retards et des fonctions de courbe pour les transitions de sortie. 🎜🎜 6. v-leave-to : Version 2.1.8 et supérieure Définit l'état final de la transition de congé. Prend effet sur l'image suivante après le déclenchement de la transition de sortie (en même temps que v-leave est supprimé), et est supprimé une fois la transition/animation terminée. 🎜🎜1.png🎜🎜Pour Pour les noms de classe qui changent pendant la transition, si vous utilisez un <transition> sans nom, v- est le préfixe par défaut pour ces noms de classe. Si vous utilisez <transition name="my-transition">, alors v-enter sera remplacé par my-transition-enter . 🎜

v-enter-active et v-leave-active peuvent contrôler différentes courbes d'assouplissement pour l'entrée/sortie des transitions. Il y aura un exemple dans le chapitre suivant. v-enter-activev-leave-active 可以控制进入/离开过渡的不同的缓和曲线,在下面章节会有个示例说明。


CSS 过渡

常用的过渡都是使用 CSS 过渡。

下面是一个简单例子:

<div id="example-1">
  <button @click="show = !show">
    Toggle render
  </button>
  <transition name="slide-fade">
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({
  el: '#example-1',
  data: {
    show: true
  }
})
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.slide-fade-enter-active {
  transition: all .3s ease;
}
.slide-fade-leave-active {
  transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active for below version 2.1.8 */ {
  transform: translateX(10px);
  opacity: 0;
}

4.gif


CSS 动画

CSS 动画用法同 CSS 过渡,区别是在动画中 v-enter 类名在节点插入 DOM 后不会立即删除,而是在 animationend 事件触发时删除。

示例:(省略了兼容性前缀)

<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>
new Vue({
  el: '#example-2',
  data: {
    show: true
  }
})
.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);
  }
}


自定义过渡的类名

我们可以通过以下特性来自定义过渡类名:

  • enter-class

  • enter-active-class

  • enter-to-class (2.1.8+)

  • leave-class

  • leave-active-class

  • leave-to-class (2.1.8+)

他们的优先级高于普通的类名,这对于 Vue 的过渡系统和其他第三方 CSS 动画库,如 Animate.css 结合使用十分有用。

示例:

<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
    name="custom-classes-transition"
    enter-active-class="animated tada"
    leave-active-class="animated bounceOutRight"
  >
    <p v-if="show">hello</p>
  </transition>
</div>
new Vue({
  el: '#example-3',
  data: {
    show: true
  }
})

6.gif


同时使用过渡和动画

Vue 为了知道过渡的完成,必须设置相应的事件监听器。它可以是 transitionendanimationend ,这取决于给元素应用的 CSS 规则。如果你使用其中任何一种,Vue 能自动识别类型并设置监听。

但是,在一些场景中,你需要给同一个元素同时设置两种过渡动效,比如 animation 很快的被触发并完成了,而 transition 效果还没结束。在这种情况中,你就需要使用 type 特性并设置 animationtransition


Transition CSSLes transitions couramment utilisées utilisent des transitions CSS.

Voici un exemple simple :

<transition :duration="1000">...</transition>
<transition :duration="{ enter: 500, leave: 800 }">...</transition>
<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>

 4.gif🎜🎜🎜🎜

🎜🎜Animation CSS🎜🎜🎜🎜L'utilisation de l'animation CSS est la même que la transition CSS, la différence est que dans l'animation v- enter Le nom de la classe ne sera pas supprimé immédiatement après l'insertion du nœud dans le DOM, mais sera supprimé lorsque l'événement animationend est déclenché. 🎜🎜Exemple : (Préfixe de compatibilité omis)🎜

// ...
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) {
    // ...
  }
}
<!--
Velocity 和 jQuery.animate 的工作方式类似,也是用来实现 JavaScript 动画的一个很棒的选择
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="example-4">
  <button @click="show = !show">
    Toggle
  </button>
  <transition
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
    v-bind:css="false"
  >
    <p v-if="show">
      Demo
    </p>
  </transition>
</div>
new Vue({
  el: '#example-4',
  data: {
    show: false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.transformOrigin = 'left'
    },
    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 })
    }
  }
})
🎜🎜🎜

🎜🎜Nom de classe de transition personnalisé🎜🎜🎜🎜Nous pouvons personnaliser le nom de la classe de transition grâce aux fonctionnalités suivantes :🎜

  • 🎜enter-class🎜
  • 🎜enter-active-class🎜< /li>
  • 🎜entrer en classe (2.1.8+)🎜
  • 🎜quitter la classe🎜
  • < li>🎜 congé-active-class🎜
  • 🎜congé en classe (2.1.8+)🎜
🎜Ils ont une priorité plus élevée que les noms de classe ordinaires, ce qui est utile pour le système de transition de Vue et d'autres bibliothèques d'animation CSS tierces, telles que Animate.css. 🎜🎜Exemple : 🎜
<transition appear>
  <!-- ... -->
</transition>
<transition
  appear
  appear-class="custom-appear-class"
  appear-to-class="custom-appear-to-class" (2.1.8+)
  appear-active-class="custom-appear-active-class"
>
  <!-- ... -->
</transition>
🎜6.gif🎜🎜🎜🎜

🎜🎜Utiliser les transitions et les animations simultanément🎜🎜🎜🎜Vue Afin de connaître l'achèvement de la transition, l'écouteur d'événement correspondant doit être défini. Il peut s'agir de transitionend ou animationend , selon les règles CSS appliquées à l'élément. Si vous utilisez l'un de ces éléments, Vue peut automatiquement reconnaître le type et configurer l'écouteur. 🎜🎜Cependant, dans certains scénarios, vous devez définir deux effets de transition pour le même élément en même temps. Par exemple, animation est déclenchée et terminée rapidement, tandis que transition. L'effet n'est pas encore terminé. Dans ce cas, vous devez utiliser l'attribut type et définir animation ou transition pour déclarer explicitement le type que vous souhaitez que Vue écoute. 🎜🎜🎜🎜🎜🎜🎜Durée de transition explicite🎜🎜🎜🎜🎜2.2.0 Nouveau🎜

Dans de nombreux cas, Vue peut déterminer automatiquement le temps d'achèvement de l'effet de transition. Par défaut, Vue attend son premier événement transitionend ou animationend sur l'élément racine de l'effet de transition. Cependant, cela n'est pas possible - par exemple, nous pourrions avoir une série de transitions soigneusement chorégraphiées dans lesquelles certains des éléments internes imbriqués ont des transitions retardées ou plus longues par rapport à l'élément racine de la transition. transitionendanimationend 事件。然而也可以不这样设定——比如,我们可以拥有一个精心编排的一系列过渡效果,其中一些嵌套的内部元素相比于过渡效果的根元素有延迟的或更长的过渡效果。

在这种情况下你可以用 <transition> 组件上的 duration 属性定制一个显性的过渡持续时间 (以毫秒计):

<transition
  appear
  v-on:before-appear="customBeforeAppearHook"
  v-on:appear="customAppearHook"
  v-on:after-appear="customAfterAppearHook"
  v-on:appear-cancelled="customAppearCancelledHook"
>
  <!-- ... -->
</transition>

你也可以定制进入和移出的持续时间:

<transition>
  <table v-if="items.length > 0">
    <!-- ... -->
  </table>
  <p v-else>Sorry, no items found.</p>
</transition>


JavaScript 钩子

可以在属性中声明 JavaScript 钩子

<transition>
  <button v-if="isEditing" key="save">
    Save
  </button>
  <button v-else key="edit">
    Edit
  </button>
</transition>
<transition>
  <button v-bind:key="isEditing">
    {{ isEditing ? 'Save' : 'Edit' }}
  </button>
</transition>

这些钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用。

当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。

推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css="false",Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。

一个使用 Velocity.js 的简单例子:

<transition>
  <button v-if="docState === 'saved'" key="saved">
    Edit
  </button>
  <button v-if="docState === 'edited'" key="edited">
    Save
  </button>
  <button v-if="docState === 'editing'" key="editing">
    Cancel
  </button>
</transition>
<transition>
  <button v-bind:key="docState">
    {{ buttonMessage }}
  </button>
</transition>

7.gif


初始渲染的过渡


可以通过 appear 特性设置节点在初始渲染的过渡

// ...
computed: {
  buttonMessage: function () {
    switch (this.docState) {
      case 'saved': return 'Edit'
      case 'edited': return 'Save'
      case 'editing': return 'Cancel'
    }
  }
}

这里默认和进入/离开过渡一样,同样也可以自定义 CSS 类名。

<transition name="fade" mode="out-in">
  <!-- ... the buttons ... -->
</transition>

自定义 JavaScript 钩子:

<transition name="component-fade" mode="out-in">
  <component v-bind:is="view"></component>
</transition>

在上面的例子中,无论是 appear 特性还是 v-on:appear 钩子都会生成初始渲染过渡。


多个元素的过渡


我们之后讨论多个组件的过渡,对于原生标签可以使用 v-if/v-else
Dans ce cas, vous pouvez personnaliser une durée de transition explicite (en millisecondes) à l'aide de l'attribut duration du composant <transition> :

new Vue({
  el: '#transition-components-demo',
  data: {
    view: 'v-a'
  },
  components: {
    'v-a': {
      template: '<div>Component A</div>'
    },
    'v-b': {
      template: '<div>Component B</div>'
    }
  }
})

Vous pouvez également personnaliser la durées d'entrée et de sortie :

.component-fade-enter-active, .component-fade-leave-active {
  transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-to
/* .component-fade-leave-active for below version 2.1.8 */ {
  opacity: 0;
}
🎜🎜🎜

Hook JavaScript🎜🎜Hooks JavaScript peuvent être déclarées dans les attributs🎜

<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>
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)
    },
  }
})
🎜Ces fonctions de hook peuvent être utilisées en conjonction avec les transitions/animations CSS ou seules. 🎜
🎜Lorsque vous utilisez uniquement JavaScript pour la transition, vous devez utiliser done pour les rappels dans enter et quitter >. Sinon, ils sont appelés de manière synchrone et la transition est terminée immédiatement. 🎜🎜
🎜Il est recommandé d'ajouter v-bind:css="false" pour les éléments qui utilisent uniquement des transitions JavaScript, Vue ignorera la détection CSS. Cela évite également l'impact du CSS lors des transitions. 🎜🎜🎜Un exemple simple utilisant Velocity.js : 🎜
.list-item {
  display: inline-block;
  margin-right: 10px;
}
.list-enter-active, .list-leave-active {
  transition: all 1s;
}
.list-enter, .list-leave-to
/* .list-leave-active for below version 2.1.8 */ {
  opacity: 0;
  transform: translateY(30px);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
<div id="flip-list-demo" class="demo">
  <button v-on:click="shuffle">Shuffle</button>
  <transition-group name="flip-list" tag="ul">
    <li v-for="item in items" v-bind:key="item">
      {{ item }}
    </li>
  </transition-group>
</div>
🎜 " alt="7.gif"/>🎜🎜🎜🎜

Transition du rendu initial


🎜Vous pouvez définir la transition du nœud dans le rendu initial via l'attribut apparaître🎜
new Vue({
  el: '#flip-list-demo',
  data: {
    items: [1,2,3,4,5,6,7,8,9]
  },
  methods: {
    shuffle: function () {
      this.items = _.shuffle(this.items)
    }
  }
})
🎜 La valeur par défaut ici est la même que pour la transition entrée/sortie, et le nom de la classe CSS peut également être personnalisé. 🎜
.flip-list-move {
  transition: transform 1s;
}
🎜Hooks JavaScript personnalisés : 🎜
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>

<div id="list-complete-demo" class="demo">
  <button v-on:click="shuffle">Shuffle</button>
  <button v-on:click="add">Add</button>
  <button v-on:click="remove">Remove</button>
  <transition-group name="list-complete" tag="p">
    <span
      v-for="item in items"
      v-bind:key="item"
      class="list-complete-item"
    >
      {{ item }}
    </span>
  </transition-group>
</div>
🎜Dans l'exemple ci-dessus, soit l'attribut apparaître, soit le crochet v-on:apparaître générera la transition de rendu initiale. 🎜🎜🎜🎜

Transition de plusieurs éléments


🎜Nous discuterons de la Transition de plusieurs composants plus tard. Pour les balises natives, vous pouvez utiliser . v -if/v-else . La transition multi-étiquette la plus courante est une liste et un élément décrivant le message indiquant que la liste est vide : 🎜🎜
new Vue({
  el: '#list-complete-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)
    },
    shuffle: function () {
      this.items = _.shuffle(this.items)
    }
  }
})
🎜 peut être utilisé comme ceci, mais il y a une chose à noter : 🎜

Lorsque des éléments avec le même nom de balise sont commutés, vous devez définir une valeur unique via l'attribut key pour les marquer afin que Vue puisse les distinguer. Sinon, Vue ne remplacera que le. contenu à l’intérieur de la même balise pour plus d’efficacité. Même si cela n'est pas techniquement nécessaire, il est préférable de définir des clés sur plusieurs éléments dans un composant <transition>. key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,给在 <transition> 组件中的多个元素设置 key 是一个更好的实践

示例:

.list-complete-item {
  transition: all 1s;
  display: inline-block;
  margin-right: 10px;
}
.list-complete-enter, .list-complete-leave-to
/* .list-complete-leave-active for below version 2.1.8 */ {
  opacity: 0;
  transform: translateY(30px);
}
.list-complete-leave-active {
  position: absolute;
}

在一些场景中,也可以通过给同一个元素的 key 特性设置不同的状态来代替 v-ifv-else,上面的例子可以重写为:

<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>

<div id="staggered-list-demo">
  <input v-model="query">
  <transition-group
    name="staggered-fade"
    tag="ul"
    v-bind:css="false"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
  >
    <li
      v-for="(item, index) in computedList"
      v-bind:key="item.msg"
      v-bind:data-index="index"
    >{{ item.msg }}</li>
  </transition-group>
</div>

使用多个 v-if 的多个元素的过渡可以重写为绑定了动态属性的单个元素过渡。例如:

new Vue({
  el: '#staggered-list-demo',
  data: {
    query: '',
    list: [
      { msg: 'Bruce Lee' },
      { msg: 'Jackie Chan' },
      { msg: 'Chuck Norris' },
      { msg: 'Jet Li' },
      { msg: 'Kung Fury' }
    ]
  },
  computed: {
    computedList: function () {
      var vm = this
      return this.list.filter(function (item) {
        return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
      })
    }
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
      el.style.height = 0
    },
    enter: function (el, done) {
      var delay = el.dataset.index * 150
      setTimeout(function () {
        Velocity(
          el,
          { opacity: 1, height: '1.6em' },
          { complete: done }
        )
      }, delay)
    },
    leave: function (el, done) {
      var delay = el.dataset.index * 150
      setTimeout(function () {
        Velocity(
          el,
          { opacity: 0, height: 0 },
          { complete: done }
        )
      }, delay)
    }
  }
})

可以重写为:

Vue.component('my-special-transition', {
  template: '\
    <transition\
      name="very-special-transition"\
      mode="out-in"\
      v-on:before-enter="beforeEnter"\
      v-on:after-enter="afterEnter"\
    >\
      <slot></slot>\
    </transition>\
  ',
  methods: {
    beforeEnter: function (el) {
      // ...
    },
    afterEnter: function (el) {
      // ...
    }
  }
})
Vue.component('my-special-transition', {
  functional: true,
  render: function (createElement, context) {
    var data = {
      props: {
        name: 'very-special-transition',
        mode: 'out-in'
      },
      on: {
        beforeEnter: function (el) {
          // ...
        },
        afterEnter: function (el) {
          // ...
        }
      }
    }
    return createElement('transition', data, context.children)
  }
})


过渡模式

这里还有一个问题,试着点击下面的按钮:

8.gif

在 “on” 按钮和 “off” 按钮的过渡中,两个按钮都被重绘了,一个离开过渡的时候另一个开始进入过渡。这是 <transition> 的默认行为 - 进入和离开同时发生。

在元素绝对定位在彼此之上的时候运行正常:

9.gif

然后,我们加上 translate 让它们运动像滑动过渡:

10.gif

同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了 过渡模式

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

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

out-in 重写之前的开关按钮过渡:

<transition v-bind:name="transitionName">
  <!-- ... -->
</transition>

11.gif

只用添加一个简单的特性,就解决了之前的过渡问题而无需任何额外的代码。

in-out

Exemple :

<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
<div id="dynamic-fade-demo" class="demo">
  Fade In: <input type="range" v-model="fadeInDuration" min="0" v-bind:max="maxFadeDuration">
  Fade Out: <input type="range" v-model="fadeOutDuration" min="0" v-bind:max="maxFadeDuration">
  <transition
    v-bind:css="false"
    v-on:before-enter="beforeEnter"
    v-on:enter="enter"
    v-on:leave="leave"
  >
    <p v-if="show">hello</p>
  </transition>
  <button
    v-if="stop"
    v-on:click="stop = false; show = false"
  >Start animating</button>
  <button
    v-else
    v-on:click="stop = true"
  >Stop it!</button>
</div>

Dans certains scénarios, vous pouvez également définir différents états pour l'attribut key du même élément au lieu de v-if et < code>v-else, l'exemple ci-dessus peut être réécrit comme :

new Vue({
  el: '#dynamic-fade-demo',
  data: {
    show: true,
    fadeInDuration: 1000,
    fadeOutDuration: 1000,
    maxFadeDuration: 1500,
    stop: true
  },
  mounted: function () {
    this.show = false
  },
  methods: {
    beforeEnter: function (el) {
      el.style.opacity = 0
    },
    enter: function (el, done) {
      var vm = this
      Velocity(el,
        { opacity: 1 },
        {
          duration: this.fadeInDuration,
          complete: function () {
            done()
            if (!vm.stop) vm.show = false
          }
        }
      )
    },
    leave: function (el, done) {
      var vm = this
      Velocity(el,
        { opacity: 0 },
        {
          duration: this.fadeOutDuration,
          complete: function () {
            done()
            vm.show = true
          }
        }
      )
    }
  }
})
12.gifLa transition de plusieurs éléments utilisant plusieurs v-if peut être réécrite pour lier la transition des attributs dynamiques d'un seul élément . Par exemple :

rrreee

peut être réécrit comme :

rrreeerrreee


🎜Transition Mode🎜🎜🎜Aussi ici Il y a une question, essayez de cliquer sur le bouton ci-dessous : 🎜🎜8.gif🎜🎜Dans la transition entre le bouton "on" et le bouton "off", les deux boutons sont redessinés, et lorsque l'un quitte la transition, l'autre commence à entrer dans la transition. Il s'agit du comportement par défaut de <transition> : l'entrée et la sortie se produisent simultanément. 🎜🎜Fonctionne bien lorsque les éléments sont positionnés absolument les uns sur les autres : 🎜🎜9.gif🎜🎜Ensuite, nous ajoutons une traduction pour les faire bouger comme des transitions coulissantes : 🎜🎜10.gif🎜🎜L'entrée et la sortie de transitions qui prennent effet simultanément ne peuvent pas répondre à toutes les exigences, donc Vue fournit un 🎜Mode Transition🎜🎜

  • 🎜in-out : le nouvel élément effectue la transition en premier, puis l'élément actuel s'éloigne. 🎜
  • 🎜out-in : l'élément actuel effectue la transition en premier, puis le nouvel élément entre. 🎜
🎜Utilisez out-in pour réécrire la transition précédente du bouton de commutation : 🎜rrreee🎜11.gif🎜🎜Ajoutez simplement une fonctionnalité simple pour résoudre le problème de transition précédent sans aucun code supplémentaire. 🎜🎜Le mode in-out n'est pas utilisé très souvent, mais il peut quand même être utile pour certains effets de transition légèrement différents. 🎜🎜Combinaison de l'exemple coulissant précédent : 🎜🎜🎜🎜🎜Cool, non ? 🎜🎜🎜🎜

Transition de plusieurs composants


La transition de plusieurs composants est beaucoup plus simple - nous n'avons pas besoin d'utiliser l'attribut key. Au lieu de cela, nous utilisons simplement des composants dynamiques :
key 特性。相反,我们只需要使用动态组件

rrreeerrreeerrreee

13.gif


列表过渡


目前为止,关于过渡我们已经讲到:

  • 单个节点

  • 同一时间渲染多个节点中的一个

那么怎么同时渲染整个列表,比如使用 v-for ?在这种场景中,使用 <transition-group> 组件。在我们深入例子之前,先了解关于这个组件的几个特点:

  • 不同于 <transition>,它会以一个真实元素呈现:默认为一个 <span>。你也可以通过 tag 特性更换为其他元素。

  • 过渡模式不可用,因为我们不再相互切换特有的元素。

  • 内部元素 总是需要 提供唯一的 key 属性值。

  • CSS 过渡的类将会应用在内部的元素中,而不是这个组/容器本身。


列表的进入/离开过渡

现在让我们由一个简单的例子深入,进入和离开的过渡使用之前一样的 CSS 类名。

rrreeerrreeerrreee

14.gif

这个例子有个问题,当添加和移除元素的时候,周围的元素会瞬间移动到他们的新布局的位置,而不是平滑的过渡,我们下面会解决这个问题。


列表的排序过渡

<transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move 特性,它会在元素的改变定位的过程中应用。像之前的类名一样,可以通过 name 属性来自定义前缀,也可以通过 move-class 属性手动设置。

v-moverrreeerrreeerrreee

13.gif🎜🎜
🎜

🎜🎜List transition🎜🎜🎜🎜🎜Jusqu'à présent, nous avons parlé de transition :
🎜
  • 🎜Single node🎜
  • 🎜Rendre l'un des plusieurs nœuds en même temps🎜
🎜Alors, comment restituer la liste entière en même temps, par exemple en utilisant v-for ? Dans ce scénario, utilisez le composant <transition-group>. Avant de plonger dans l'exemple, comprenons d'abord quelques fonctionnalités de ce composant : 🎜
  • 🎜 est différent de <transition>, Il sera rendu comme un élément réel : par défaut un <span>. Vous pouvez également le remplacer par d'autres éléments en utilisant l'attribut tag. 🎜
  • 🎜Le Le mode transition n'est pas disponible car nous ne basculons plus entre les uns les autres éléments uniques. 🎜
  • 🎜Les éléments internes 🎜exigent toujours🎜 de fournir une valeur d'attribut key unique. 🎜
  • 🎜Les classes de transition CSS seront appliquées aux éléments internes, pas au groupe/conteneur lui-même. 🎜
🎜
🎜

🎜Transition entrée/sortie pour la liste🎜🎜🎜 🎜Plongeons maintenant dans un exemple simple, en utilisant les mêmes noms de classes CSS pour les transitions d'entrée et de sortie. 🎜rrreeerrreeerrreee🎜14.gif🎜🎜 Il y a un problème avec cet exemple. Lors de l'ajout et de la suppression d'éléments, les éléments environnants se déplaceront instantanément vers leurs nouvelles positions de disposition au lieu d'une transition en douceur. Nous allons résoudre ce problème ci-dessous. 🎜🎜
🎜

🎜Tri de la transition de la liste🎜🎜🎜🎜<transition-group> a une autre particularité. Non seulement vous pouvez entrer et sortir des animations, mais vous pouvez également modifier le positionnement. Pour utiliser cette nouvelle fonctionnalité, il suffit de connaître la nouvelle fonctionnalité 🎜v-move🎜, qui sera appliquée lors du repositionnement de l'élément. Comme le nom de classe précédent, le préfixe peut être personnalisé via l'attribut name, ou il peut être défini manuellement via l'attribut move-class. 🎜🎜v-move est très utile pour définir le timing de commutation et la courbe de transition de la transition. Vous verrez l'exemple suivant : 🎜.rrreeerrreeerrreee

15.gif

Cela a l'air incroyable en interne, Vue utilise une simple file d'attente d'animation appelée FLIP
qui utilise des transformations pour faire passer en douceur les éléments de leur position précédente à leur nouvelle position.

Nous avons combiné l'exemple précédemment implémenté avec cette technologie afin que tous les changements dans notre liste aient des transitions animées.

rrreeerrreeerrreee

16.gif

Il convient de noter que les éléments utilisant la transition FLIP ne peuvent pas être définis sur display: inline . Comme alternative, il peut être défini sur display: inline-block ou placé dans flex display: inline 。作为替代方案,可以设置为 display: inline-block 或者放置于 flex 中

FLIP 动画不仅可以实现单列过渡,多维网格也同样可以过渡

17.gif


列表的交错过渡

通过 data 属性与 JavaScript 通信 ,就可以实现列表的交错过渡:

rrreeerrreee

18.gif


可复用的过渡


过渡可以通过 Vue 的组件系统实现复用。要创建一个可复用过渡组件,你需要做的就是将 <transition> 或者 <transition-group> 作为根组件,然后将任何子组件放置在其中就可以了。

使用 template 的简单例子:

rrreee

函数式组件 更适合完成这个任务:

rrreee


动态过渡


在 Vue 中即使是过渡也是数据驱动的!动态过渡最基本的例子是通过 name


L'animation FLIP peut non seulement réaliser une transition à une seule colonne, mais également une grille multidimensionnelle peut également faire l'objet d'une transition

 :

liste Transition échelonnée

En communiquant avec JavaScript via l'attribut data, vous pouvez réaliser la transition échelonnée de la liste :

rrreeerrreee19.gif18.gif

🎜🎜🎜

Transitions réutilisables


🎜Les transitions peuvent être réutilisées via le système de composants de Vue. Pour créer un composant de transition réutilisable, tout ce que vous avez à faire est de faire de <transition> ou <transition-group> le composant racine, puis de placer les composants enfants. dedans. 🎜🎜🎜Un exemple simple d'utilisation d'un modèle : 🎜rrreee🎜
Les composants fonctionnels🎜 sont plus adaptés à cette tâche : 🎜rrreee🎜🎜🎜

Transition dynamique


🎜 Même les transitions sont pilotées par les données dans Vue ! L'exemple le plus basique de transition dynamique consiste à lier des valeurs dynamiques via l'attribut name. 🎜🎜rrreee🎜 Ceci est utile lorsque vous souhaitez basculer entre différentes transitions à l'aide des transitions/animations CSS définies par le système de transition de Vue. 🎜🎜Toutes les propriétés de transition peuvent être liées dynamiquement, mais nous n'avons pas seulement les propriétés dont nous pouvons profiter, nous pouvons également obtenir toutes les données dans le contexte via des hooks d'événement, car les hooks d'événement sont toutes des méthodes. Cela signifie que vos transitions JavaScript se comporteront différemment selon l'état du composant. 🎜rrreeerrree🎜🎜🎜

Enfin, la solution ultime pour créer des transitions dynamiques consiste pour le composant à modifier dynamiquement la transition précédente en acceptant les accessoires. Comme le dit le vieil adage, la seule limite est votre imagination.