Вход / выход и список переходов
обзор
Vue.js предоставляет различные способы применения переходов, когда элементы вставляются, обновляются или удаляются из DOM. Эти способы включают инструменты для:
- применять классы для CSS-переходов и анимации автоматически
- интегрировать сторонние библиотеки анимации CSS, например Animate.css
- использовать JavaScript для манипулирования DOM непосредственно во время переходов
- интегрировать сторонние библиотеки анимации JavaScript, например, Velocity.js
Переход отдельных элементов / компонентов
Vue предоставляет нам компонент-оболочку перехода, который позволяет нам добавлять входящие / выходящие переходы для любого компонента или элемента в следующем контексте:
- Условный рендеринг с использованием v-if
- Динамические компоненты
- Компонент корневых узлов
- Условное отображение с использованием v-show>
Пример показан ниже:
HTML
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
JS
new Vue({
el: '#demo',
data: {
show: true
}
})
CSS
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
Переходные классы
Шесть классифицированных могут применяться для входа / выхода из перехода.
- v-enter: начальное состояние для ввода.
- v-enter-active: активное состояние для ввода.
- v-enter-to: конечное состояние для ввода.
- V-отпуск: начальное состояние для отпуска.
- V-Leave-Active: активное состояние для отпуска.
- v-отпуск-до: конечное состояние для отпуска.
Все эти классы будут иметь префикс с именем перехода. Префикс v является префиксом по умолчанию, когда мы используем элемент <transition> без имени. но если у нас было <transition name = "my-transition">, тогда мы можем изменить v-enter на my-transition-enter.
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
}
})
CSS
.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);
}
transform: translateX(10px);
opacity: 0;
}
CSS анимация
Мы можем применять CSS-анимации почти так же, как мы применяем CSS-переходы, с той разницей, что v-enter не удаляется сразу после вставки элемента, а происходит при анимации события:
HTML
<div id="example-2">
<button @click="show = !show">Toggle show</button>
<transition name="bounce">
<p v-if="show"> some sample Lorem ipsum</p>
</transition>
</div>
JS
new Vue({
el: '#example-2',
data: {
show: true
}
})
CSS
.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);
}
}
Пользовательские классы переходов
Мы можем указать пользовательские классы переходов для переопределения обычных имен классов, предоставив следующие атрибуты:
- введите класс
- введите активный класс
- вход в класс (2.1.8+)
- несмываемый класс
- несмываемые активный класс
- уйти в класс (2.1.8+)
это важно, когда мы хотим использовать внешнюю библиотеку CSS вместе с системой переходов Vue.
Совместное использование переходов и анимации
Чтобы это произошло, нам нужно подключить прослушиватели событий, чтобы знать, когда завершился переход. Это может быть или переход или анимация, это зависит от типа применяемых правил CSS.
Однако, когда нам нужны оба этих элемента в одном и том же элементе, нам придется явно объявить тип, о котором Vue будет заботиться, в атрибуте типа со значением перехода или анимации.
Длительность явного перехода
По умолчанию Vue ожидает первого анимационного или переходного события в корневом элементе перехода. Но бывают случаи, когда это нежелательно, так как в этом случае мы можем указать явную продолжительность перехода (в миллисекундах), используя свойство duration для компонента <transition>.
Кроме того, мы можем указать отдельные значения для продолжительности ввода и выхода:
<transition :duration="{ enter: 500, leave: 800 }">...</transition>
JavaScript Крюки
мы можем определить хуки JavaScript в атрибутах:
HTML
<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>
JS
methods: {
// --------
// ENTERING
// --------
beforeEnter: function (el) {
// ...
},
enter: function (el, done) {
// ...
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// --------
// LEAVING
// --------
beforeLeave: function (el) {
// ...
},
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
leaveCancelled: function (el) {
// ...
}
}
Перечисленные выше хуки могут использоваться сами по себе или в сочетании с CSS-переходами / анимациями.
Мы рекомендуем явно добавить v-bind: css = "false" для переходов только на JavaScript, чтобы Vue мог пропустить обнаружение CSS. Таким образом, предотвращение случайного вмешательства правил CSS в переход. Пример использования Velocity.js показан ниже:
HTML
<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>
JS
new Vue({
el: '#example-4',
data: {
show: 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 })
}
}
})
Переходы на Intial Render
если мы хотим применить переход к исходному рендеру узла, мы можем добавить атрибут emerge так:
<transition appear>
<!-- ... -->
</transition>
Это будет использовать переход, указанный для входа и выхода по умолчанию. Но вы можете указать свои классы CSS, если хотите: <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>
А также пользовательские хуки JavaScript:
<transition
appear
v-on:before-appear="customBeforeAppearHook"
v-on:appear="customAppearHook"
v-on:after-appear="customAfterAppearHook"
v-on:appear-cancelled="customAppearCancelledHook"
>
<!-- ... -->
</transition>
Переход между элементами
Мы также можем переходить между необработанными элементами, используя v-if / v-else. Один из наиболее распространенных двухэлементных переходов между контейнером списка и сообщением, описывающим пустой список:
<transition>
<table v-if="items.length > 0">
<!-- ... -->
</table>
<p v-else>Sorry, no item was found.</p>
</transition>
Хотя это работает хорошо, но есть одно предостережение, о котором мы должны знать:
Когда мы переключаемся между элементами с одинаковым именем тега, мы должны сказать Vue, что они являются отдельными элементами, предоставив им уникальные ключевые атрибуты. Иначе, компилятор Vue будет заменять содержимое элемента только для эффективности.
Взять, к примеру:
<transition>
<button v-if="isEditing" key="save">
Save
</button>
<button v-else key="edit">
Edit
</button>
</transition>
Мы можем использовать директиву v-bind вместо использования v-if и v-else:
<transition>
<button v-bind:key="isEditing">
{{ isEditing ? 'Save' : 'Edit' }}
</button>
</transition>
Для нас также возможно переходить между любым количеством элементов, независимо от того, используем ли мы v-if или v-bind одного элемента с динамическим свойством.
HTML
<transition>
<button v-bind:key="docState">
{{ buttonMessage }}
</button>
</transition>
JS
// ...
```computed: {
buttonMessage: function () {
switch (this.docState) {
case 'saved': return 'Edit'
case 'edited': return 'Save'
case 'editing': return 'Cancel'
}
}
}
Переходные режимы
Вход и выход из переходов одновременно не всегда желательны, поэтому Vue предлагает несколько альтернативных режимов перехода:
- in-out: сначала переходят новые элементы, затем, когда он завершается, текущий элемент будет выходить.
- out-in: текущие элементы переходят сначала, затем, когда он завершается, новый элемент будет переходить внутрь.
Переход между компонентами
Переход между компонентами проще, у нас нет ключевого атрибута, скорее, мы обернем динамический компонент:
HTML
<transition name="component-fade" mode="out-in">
<component v-bind:is="view"></component>
</transition>
JS
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>'
}
}
})
CSS
.component-fade-enter-active, .component-fade-leave-active {
transition: opacity .3s ease;
}
.component-fade-enter, .component-fade-leave-to
/* .component-fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
Список переходов
До сих пор мы управляли переходами для:
- Отдельные узлы
- Несколько узлов, где только один узел отображается одновременно.
- В отличие от <transition>, здесь отображается фактический элемент: a <span> по умолчанию. Вы можете изменить элемент, который отображается с атрибутом тега.
- Режимы перехода недоступны, потому что мы больше не чередуем взаимоисключающие элементы.
- Элементы внутри, как правило, должны иметь уникальный ключевой атрибут.
- CSS переходные классы будут применяться к внутренним элементам, а не к самим группам / контейнерам.
Так что если у нас есть целый список элементов для одновременной визуализации, тогда мы будем использовать компонент <transition-group>. Есть несколько вещей, которые важно знать об этом компоненте, прежде чем мы углубимся в примеры.
Перечисление Входов / Выходов из Переходов
Вот пример перехода входа и выхода с использованием классов CSS, которые мы использовали ранее:
HTML
<div id="list-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>
JS
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)
},
}
})
CSS
.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 below version 2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}
В приведенном выше примере, когда мы добавляем или удаляем элемент, окружающие его элементы мгновенно переходят на новое место вместо плавного перехода.
Перемещение по списку
<Transition-group> не только оживляет вход и выход, но и меняет положение. Новая концепция, которую мы должны знать, чтобы использовать эту функцию, это добавление класса v-move.
HTML
<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>
JS
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)
}
}
})
CSS
.flip-list-move {
transition: transform 1s;
}
Код выше можно использовать вместе с предыдущим примером кода для добавления / удаления номеров.
HTML
<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>
JS
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)
}
}
})
CSS
.list-complete-item {
transition: all 1s;
display: inline-block;
margin-right: 10px;
}
.list-complete-enter, .list-complete-leave-to
/* .list-complete-leave-active below version 2.1.8 */ {
opacity: 0;
transform: translateY(30px);
}
.list-complete-leave-active {
position: absolute;
}
Потрясающие списки переходов
Также возможно поменять местами переход в списке, связавшись с переходом JavaScript через атрибуты данных:
HTML
<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>
JS
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. Для этого мы используем <transition> или <transition-group> в корне, а затем передаем все дочерние элементы в компонент перехода.
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)
}
})
Динамические переходы
Переходы в Vue также управляются данными. Самый простой пример динамического перехода будет связывать атрибут name с динамическим свойством.
<transition v-bind:name="transitionName">
<!-- ... -->
</transition>
Затем мы определяем CSS-переходы / анимации, используя соглашения классов переходов Vue, и хотим переключаться между ними. Любой атрибут перехода может быть динамически связан.
Однако наилучшим способом создания динамических переходов является использование компонентов, принимающих реквизиты, для изменения природы переходов, которые будут использоваться.
Новый контент: Composer: менеджер зависимостей для PHP , R программирования