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) } })
动态过渡
所有过渡 attribute 都可以动态绑定,但我们不仅仅只有 attribute 可以利用,还可以通过事件钩子获取上下文中的所有数据,因为事件钩子都是方法。这意味着,根据组件的状态不同,你的 JavaScript 过渡会有不同的表现。
<div id="bind-animation">
FadeIn<input type="range" v-model="fadeIn" max="10" min="0" />{{fadeIn}}
FadeOut<input type="range" v-model="fadeOut" max="10" min="0" />{{fadeOut}}
<button @click="show = show == true ? false : true" >{{show}}</button>
<transition ref="helloTransition" @enter="enterFunt" @leave="leaveFunt">
<h3 ref="hello" v-show="show">hello</h3>
</transition>
</div>
<script>
var vm = new Vue({
el: '#bind-animation',
data(){
return {
fadeIn: 5,
fadeOut: 5,
show: true,
}
},
methods:{
enterFunt(el,done){
this.$refs.hello.style = 'opacity: 1';
this.$refs.hello.style.transitionDuration = this.fadeIn+'s';
},
leaveFunt(el,done){
this.$refs.hello.style = 'opacity: 0';
this.$refs.hello.style.transitionDuration = this.fadeOut+'s';
},
}
})
</script>
<style>
.hello-enter-active,.hello-leave-active{
transition-duration: 5s;
transition-timing-function: ease;
}
</style>
状态过渡
通过侦听器我们能监听到任何数值 property 的数值更新。
<div id="count-roll">
<input v-model="count" type="number" step="10" min="0"/>
<transition name="roll">
<h3 ref="roll">{{frontNum}}</h3>
</transition>
</div>
<script>
var vm = new Vue({
el: '#count-roll',
data(){
return {
count: 0,
frontNum: 0,
intervalID:0,
}
},
watch:{
async count(newV,oldV){
this.intervalID = await setInterval(()=>{
this.rollNum()
},30)
}
},
methods:{
rollNum(){
if(this.frontNum < this.count)this.frontNum++;
else if(this.frontNum > this.count)this.frontNum--;
else clearInterval(this.intervalID)
}
}
})
</script>
<style>
.roll-enter-active{
transition-timing-function: ease;
}
</style>
动态状态过渡
<!DOCTYPE html>
<html>
<head>
<title>Dynamic State Transitions</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenLite.min.js"></script>
<script src="https://unpkg.com/vue@2"></script>
<style>
svg {
display: block;
}
polygon {
fill: #41b883;
}
circle {
fill: transparent;
stroke: #35495e;
}
input[type="range"] {
display: block;
width: 100%;
margin-bottom: 15px;
}
</style>
</head>
<body>
<div id="app">
<svg width="200" height="200">
<polygon :points="points"></polygon>
<circle cx="100" cy="100" r="90"></circle>
</svg>
<label>Sides: {{ sides }}</label>
<input type="range" min="3" max="500" v-model.number="sides" />
<label>Minimum Radius: {{ minRadius }}%</label>
<input type="range" min="0" max="90" v-model.number="minRadius" />
<label>Update Interval: {{ updateInterval }} milliseconds</label>
<input type="range" min="10" max="2000" v-model.number="updateInterval" />
</div>
<script>
new Vue({
el: "#app",
data: function() {
var defaultSides = 10;
var stats = Array.apply(null, { length: defaultSides }).map(function() {
return 100;
});
return {
stats: stats,
points: generatePoints(stats),
sides: defaultSides,
minRadius: 50,
interval: null,
updateInterval: 500
};
},
watch: {
sides: function(newSides, oldSides) {
var sidesDifference = newSides - oldSides;
if (sidesDifference > 0) {
for (var i = 1; i <= sidesDifference; i++) {
this.stats.push(this.newRandomValue());
}
} else {
var absoluteSidesDifference = Math.abs(sidesDifference);
for (var i = 1; i <= absoluteSidesDifference; i++) {
this.stats.shift();
}
}
},
stats: function(newStats) {
// 时间轴实现动画(数据对象,时间周期,点)
TweenLite.to(this.$data, this.updateInterval / 1000, {points: generatePoints(newStats)});
},
updateInterval: function() {
this.resetInterval();
}
},
mounted: function() {
this.resetInterval();
},
methods: {
randomizeStats: function() {
var vm = this;
this.stats = this.stats.map(function() {
return vm.newRandomValue();
});
},
newRandomValue: function() {
return Math.ceil(
this.minRadius + Math.random() * (100 - this.minRadius)
);
},
resetInterval: function() {
var vm = this;
clearInterval(this.interval);
this.randomizeStats();
this.interval = setInterval(function() {
vm.randomizeStats();
}, this.updateInterval);
}
}
});
function valueToPoint(value, index, total) {
var x = 0;
var y = -value * 0.9;
var angle = ((Math.PI * 2) / total) * index;
var cos = Math.cos(angle);
var sin = Math.sin(angle);
var tx = x * cos - y * sin + 100;
var ty = x * sin + y * cos + 100;
return { x: tx, y: ty };
}
function generatePoints(stats) {
var total = stats.length;
return stats.map(function(stat, index) {
var point = valueToPoint(stat, index, total);
return point.x + "," + point.y;
}).join(" ");
}
</script>
</body>
</html>