1. 过渡 and 动画overview
Vue.jsproviding了一套完整 过渡 and 动画system, 允许我们 in 元素进入 or 离开DOM时application过渡效果, 以及 in 元素status变化时application动画效果.
1.1 过渡 and 动画 区别
- 过渡: 元素 from 一种status平滑过渡 to 另一种status, 通常涉及 to CSSproperty 变化, such asopacity, transformetc..
- 动画: 元素执行一系列预定义 动画效果, 通常usingCSS动画 or JavaScript动画implementation.
1.2 Vue过渡 application场景
- 元素 显示/隐藏 (v-if/v-show)
- component 挂载/卸载
- routing切换
- list 添加/delete/sort
2. 单元素/component 过渡
Vueproviding了<transition>component来implementation单元素 or 单component 过渡效果.
2.1 basicusing
<transition name="fade">
<div v-if="show" class="demo-box">Hello Vue!</div>
</transition>
<button @click="show = !show">切换显示/隐藏</button>
当元素进入 or 离开DOM时, Vue会自动添加/移除以 under class名:
- v-enter: 进入过渡 开始status
- v-enter-active: 进入过渡 激活status
- v-enter-to: 进入过渡 结束status
- v-leave: 离开过渡 开始status
- v-leave-active: 离开过渡 激活status
- v-leave-to: 离开过渡 结束status
such as果using了nameproperty, such asname="fade", 则class名会变 for :
- fade-enter
- fade-enter-active
- fade-enter-to
- fade-leave
- fade-leave-active
- fade-leave-to
2.2 过渡class名 持续时间
Vue会automatically detect过渡效果 持续时间. such as果需要手动指定, 可以usingdurationproperty:
<transition name="fade" :duration="1000">
<div v-if="show" class="demo-box">Hello Vue!</div>
</transition>
<!-- 分别指定进入 and 离开 持续时间 -->
<transition name="fade" :duration="{ enter: 500, leave: 800 }">
<div v-if="show" class="demo-box">Hello Vue!</div>
</transition>
2.3 自定义过渡class名
可以using自定义 过渡class名, 这些class名priority high 于默认class名:
- enter-class
- enter-active-class
- enter-to-class
- leave-class
- leave-active-class
- leave-to-class
这使得我们可以方便地using第三方动画library, such asAnimate.css:
<!-- 引入Animate.css -->
<link href="https://cdn.jsdelivr.net/npm/animate.css@4.1.1/animate.min.css" rel="stylesheet">
<!-- usingAnimate.css 动画效果 -->
<transition
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOut"
>
<div v-if="show" class="demo-box">Hello Vue!</div>
</transition>
2.4 JavaScripthookfunction
可以usingJavaScripthookfunction来implementation更 complex 过渡效果:
<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"
>
<div v-if="show" class="demo-box">Hello Vue!</div>
</transition>
methods: {
beforeEnter: function(el) {
// 进入过渡 before callback
el.style.opacity = 0;
el.style.transform = 'translateX(100px)';
},
enter: function(el, done) {
// 进入过渡 callback, done is 必须调用
el.offsetWidth; // 触发重排
el.style.opacity = 1;
el.style.transform = 'translateX(0)';
done(); // 必须调用donefunction, 否则after-enter不会触发
},
afterEnter: function(el) {
// 进入过渡completion after callback
console.log('Enter transition completed');
},
enterCancelled: function(el) {
// 进入过渡被取消时 callback
console.log('Enter transition cancelled');
},
beforeLeave: function(el) {
// 离开过渡 before callback
el.style.opacity = 1;
el.style.transform = 'translateX(0)';
},
leave: function(el, done) {
// 离开过渡 callback, done is 必须调用
el.offsetWidth; // 触发重排
el.style.opacity = 0;
el.style.transform = 'translateX(-100px)';
done(); // 必须调用donefunction, 否则after-leave不会触发
},
afterLeave: function(el) {
// 离开过渡completion after callback
console.log('Leave transition completed');
},
leaveCancelled: function(el) {
// 离开过渡被取消时 callback (仅用于v-show)
console.log('Leave transition cancelled');
}
}
提示
usingJavaScripthookfunction时, 需要注意 in enter and leavehookin调用donefunction, 否则Vue无法知道过渡when结束.
3. list过渡
Vueproviding了<transition-group>component来implementationlist 过渡效果, includinglist项 添加, delete and sort.
3.1 basicusing
<transition-group name="list" tag="ul">
<li
v-for="item in items"
:key="item.id"
class="list-item"
>
{{ item.name }}
<button @click="removeItem(item.id)">delete</button>
</li>
</transition-group>
<button @click="addItem">添加项</button>
data: function() {
return {
items: [
{ id: 1, name: '项 1' },
{ id: 2, name: '项 2' },
{ id: 3, name: '项 3' }
],
nextId: 4
};
},
methods: {
addItem: function() {
this.items.push({ id: this.nextId++, name: '项 ' + this.nextId });
},
removeItem: function(id) {
this.items = this.items.filter(item => item.id !== id);
}
}
3.2 listsort过渡
<transition-group>component还supportlist项 sort过渡, throughv-moveclass名implementation:
<!-- listsort过渡 -->
<transition-group name="list" tag="ul">
<li
v-for="item in sortedItems"
:key="item.id"
class="list-item"
>
{{ item.name }}
<input v-model.number="item.order" type="number">
</li>
</transition-group>
<!-- CSS样式 -->
.list-move, .list-enter-active, .list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from, .list-leave-to {
opacity: 0;
transform: translateX(30px);
}
/* 确保delete时 过渡效果 */
.list-leave-active {
position: absolute;
}
warning
usinglist过渡时, 必须 for 每个list项providing唯一 key值, 否则过渡效果可能无法正常工作.
3.3 list交错过渡
可以usingJavaScripthookfunctionimplementationlist项 交错过渡效果:
<transition-group
name="stagger"
tag="ul"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
>
<li
v-for="(item, index) in items"
:key="item.id"
:data-index="index"
class="list-item"
>
{{ item.name }}
</li>
</transition-group>
methods: {
beforeEnter: function(el) {
el.style.opacity = 0;
el.style.height = 0;
},
enter: function(el, done) {
const delay = el.dataset.index * 150;
setTimeout(() => {
el.style.opacity = 1;
el.style.height = el.scrollHeight + 'px';
done();
}, delay);
},
leave: function(el, done) {
const delay = el.dataset.index * 150;
setTimeout(() => {
el.style.opacity = 0;
el.style.height = 0;
done();
}, delay);
}
}
4. status过渡
除了进入/离开DOM 过渡, Vue还support元素status变化 过渡, such as颜色, 尺寸etc. 变化.
4.1 动态过渡
可以using动态 nameproperty来切换不同 过渡效果:
<transition :name="transitionName">
<div v-if="show" class="demo-box">Hello Vue!</div>
</transition>
<button @click="show = !show">切换显示/隐藏</button>
<select v-model="transitionName">
<option value="fade">淡入淡出</option>
<option value="slide">滑动</option>
<option value="scale">缩放</option>
<option value="bounce">弹跳</option>
</select>
4.2 条件过渡
可以根据条件来决定 is 否application过渡效果:
<transition :name="show ? 'fade' : 'slide'">
<div v-if="show" class="demo-box">Hello Vue!</div>
</transition>
4.3 动态component过渡
可以using<transition>componentpackage裹<component>component, implementation动态component 过渡效果:
<transition name="component-fade" mode="out-in">
<component :is="currentComponent"></component>
</transition>
<button @click="toggleComponent">切换component</button>
data: function() {
return {
currentComponent: 'ComponentA'
};
},
methods: {
toggleComponent: function() {
this.currentComponent = this.currentComponent === 'ComponentA' ? 'ComponentB' : 'ComponentA';
}
},
components: {
'ComponentA': {
template: '<div class="demo-box">component A</div>'
},
'ComponentB': {
template: '<div class="demo-box" style="background-color: #34A853;">component B</div>'
}
}
4.4 过渡模式
当using<transition>componentpackage裹两个 or many 个元素时, 可以usingmodeproperty来控制过渡 顺序:
- in-out: new 元素先进入, old 元素再离开
- out-in: old 元素先离开, new 元素再进入
<transition name="fade" mode="out-in">
<component :is="currentComponent" key="currentComponent"></component>
</transition>
5. 过渡 performanceoptimization
5.1 usingtransformproperty
in 过渡效果in, 优先usingtransformproperty (such astranslate, scale, rotateetc.) , 而不 is top, leftetc.property, 因 for transformproperty可以触发GPU加速, improving动画performance.
5.2 usingwill-changeproperty
for 于频繁发生 动画, 可以usingwill-changeproperty来告诉浏览器提 before 准备, improving动画performance:
.demo-box {
will-change: transform, opacity;
}
5.3 避免过度using动画
虽然动画可以增强user体验, 但过度using动画会导致页面performance under 降, 影响user体验. 因此, 应该只 in 必要 地方using动画, 并保持动画效果简洁流畅.
5.4 usingCSS动画而非JavaScript动画
in 可能 circumstances under , 优先usingCSS动画, 而不 is JavaScript动画, 因 for CSS动画可以更 good 地利用浏览器 硬件加速, performance更 good .
6. best practices
6.1 选择合适 过渡效果
- 淡入淡出效果适合 big many 数场景, 简洁 big 方
- 滑动效果适合侧edge栏, 菜单etc.
- 缩放效果适合弹窗, 模态框etc.
- 弹跳效果适合强调某个元素
6.2 保持过渡效果一致
in 整个applicationin, 应该保持过渡效果 consistency, 避免using过 many 不同 过渡效果, 导致视觉混乱.
6.3 合理设置过渡持续时间
过渡持续时间应该根据具体circumstancesfor调整, 一般来说:
- 淡入淡出效果: 300-500ms
- 滑动效果: 300-600ms
- 缩放效果: 300-500ms
- complex 动画: 500-1000ms
6.4 考虑无障碍访问
in using动画时, 应该考虑 to 无障碍访问, for userproviding关闭动画 选项, 因 for 某些user可能 for 动画敏感.
练习 1: basic过渡效果
- creation一个按钮, 点击时切换元素 显示/隐藏.
- for 元素添加淡入淡出过渡效果.
- for 元素添加滑动过渡效果.
- for 元素添加缩放过渡效果.
- using动态nameproperty切换不同 过渡效果.
练习 2: list过渡
- creation一个list, support添加, delete and sortfunctions.
- for list项 添加 and delete添加过渡效果.
- for list项 sort添加过渡效果.
- implementationlist项 交错过渡效果.
练习 3: component过渡
- creation两个component, ComponentA and ComponentB.
- implementationcomponent之间 切换functions.
- for component切换添加过渡效果.
- 尝试using不同 过渡模式 (in-out and out-in) .
- using第三方动画library (such asAnimate.css) for component切换添加更 complex 动画效果.