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>

image

动态状态过渡

https://codesandbox.io/s/github/vuejs/vuejs.org/tree/master/src/v2/examples/vue-20-dynamic-state-transitions?file=/index.html:0-3815

<!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>
posted @ 2022-08-13 18:08  ~LemonWater  阅读(71)  评论(0编辑  收藏  举报