前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【云+社区年度征文】Vue深入dom到组件动画

【云+社区年度征文】Vue深入dom到组件动画

原创
作者头像
瑞新
修改2020-12-21 09:30:57
2.3K0
修改2020-12-21 09:30:57
举报

toc

dom和vue对比

Helloworld

注意:下载官方js开发vue.js引入项目

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>hello world</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">{{content}}</div>
		<script>
				// dom
				// var dom = document.getElementById('app');
				// dom.innerHTML = 'hello world'
				
				// vue
				var app = new Vue({
					el: '#app',
					data:{
						content: 'hello world'
					}
				})
			</script>
	</body>
</html>

计时器对比

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>hello world</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">{{content}}</div>
		<script>
				// dom
				// var dom = document.getElementById('app');
				// dom.innerHTML = 'hello world'
				// setTimeout(function() {
				// 	dom.innerHTML = 'bye world'				
				// }, 2000)
				
				// vue
				var app = new Vue({
					el: '#app',
					data:{
						content: 'hello world'
					}
				})
				setTimeout(function(){
					app.$data.content = 'bye world'
				}, 2000)
			</script>
	</body>
</html>

todoList练习

添加任务标记

V-for,方法绑定,双向绑定v-model

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<input type="text" v-model="inputValue"/>
			<button type="button" v-on:click="handleBtnClick" >添加</button>
			<ul>
				<li v-for="item in list">{{item}}</li>
			</ul>
			
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					list: [],
					inputValue: ''
				},
				methods:{
					handleBtnClick: function() {
						this.list.push(this.inputValue)
						this.inputValue = ''
					}
				}
			})
		</script>
	</body>
</html>

mvp对比MVVM

mvp,p层处理逻辑,关注dom操作 比如jq案例2-4

MV,VM是Vue提供,关注model操作(es5:obj.properties(对象性能、内容)+虚拟dom)

代码量提升30-60%

组件化-todoList

一个页面拆分层多个便于单独管理的组件

todoList中拆分li标签组件化

全局组件Vue.component、局部组件var TodoItem = {、组件传值接收父值v-bind:content="item" props:'content',

简写 点击事件@click=“” 等价 v-on:click=""

简写 传递变量:xxx 等价 v-bind:xxx=""

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<input type="text" v-model="inputValue"/>
			<button type="button" v-on:click="handleBtnClick" >添加</button>
			<ul>
				<!-- v-bind:xx 简写 :xx 给子组件传入一个绑定 -->
				<todo-item 	:content="item"
							:index="index"
							v-for="(item, index) in list"
							@delete="handleItemDelete"></todo-item>
			</ul>
		</div>
		<script>
			// 全局组件 注意大写,引用时默认-连接大写
			// props接收父组件的变量
			// Vue.component("TodoItem", {
			// 	props:['content'],
			// 	template: "<li>{{content}}</li>"
			// })
			
			//局部组件,必须去vue实例中注册组件
			var TodoItem = {
				props:['content', 'index'],
				template: "<li @click='handleItemClick' >{{content}}</li>",
				methods: {
					handleItemClick: function(){
						//子组件触发父组件
						this.$emit("delete", this.index)
					}
				}
			}
			var app = new Vue({
				el: '#app',
				components: {
					TodoItem: TodoItem
				},
				data: {
					list: [],
					inputValue: ''
				},
				methods:{
					handleBtnClick: function() {
						this.list.push(this.inputValue)
						this.inputValue = ''
					},
					// 子组件触发的父组件删除
					handleItemDelete: function(index) {
						// splice从传入的下标开始删除一项
						this.list.splice(index, 1)
					}
				}
			})
		</script>
	</body>
</html>

Vue实例的生命周期钩子

8个生命周期 api中查看有11个

创建、渲染(后有更新)、销毁各两个+active+error

Vue模板语法

其他点击绑定变量见组件化的案例

显示文本,并支持js

插值{{}}和v-text一样,进行文本转义可以正常显示标签

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Vue模板语法</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 显示文本,并支持js -->
			{{msg + ' add'}}
			<div v-text="msg + ' add'"></div>
			<div v-html="msg + ' add'"></div>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					msg: '<h1>hello</h1>'
				}
			})
		</script>
	</body>
</html>

<img src="http://bennyrhys_mr.gitee.io/images_bed/images/vue/Vue2.5%E5%BC%80%E5%8F%91%E5%8E%BB%E5%93%AA%E5%84%BF%E7%BD%91App/Vue%20%E8%B5%B7%E6%AD%A5.assets/image-20201115154854389.png" alt="image-20201115154854389" style="zoom:50%;" />

/images/vue/Vue2.5开发去哪儿网App/Vue%20起步.assets/image-20201115154854389.png

https://bennyrhys_mr.gitee.io/images/vue/Vue2.5%E5%BC%80%E5%8F%91%E5%8E%BB%E5%93%AA%E5%84%BF%E7%BD%91App/Vue%20%E8%B5%B7%E6%AD%A5.assets/image-20201115154854389.png

http://bennyrhys_mr.gitee.io/images_bed/images/vue/Vue2.5%E5%BC%80%E5%8F%91%E5%8E%BB%E5%93%AA%E5%84%BF%E7%BD%91App/Vue%20%E8%B5%B7%E6%AD%A5.assets/image-20201115154854389.png

计算属性、方法、监听

意义:不要在插值属性中进行计算拼接。单独通过computed缓存属性计算并返回

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 计算属性 触发无需加() -->
			<!-- {{fullName}}
			{{age}} -->
			
			<!-- 方法实现计算属性 触发需加() -->
			<!-- {{fullName()}}
			{{age}} -->
			
			<!-- 监听器 -->
			{{fullName}}
			{{age}}
			
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					firstName: 'benny',
					lastName: 'rhys',
					fullName: 'benny rhys',
					age: 28
				},
				// 监听器 (不建议,有类缓存机制,但代码量多)
				watch: {
					// 监听的字段
					firstName: function() {
						console.log("加载一次");
						this.fullName = this.firstName + " " + this.lastName;
					},
					lastName: function() {
						console.log("加载一次");
						this.fullName = this.firstName + " " + this.lastName;
					}
				}
				
				//方法 (不建议,无缓存机制)
				// methods: {
				// 	//实现计算属性
				// 	fullName: function() {
				// 	console.log("加载一次")
				// 	return this.firstName + " " + this.lastName;
				// 	}
				// }
				
				//计算属性(缓存机制,所依赖的变量改变才重新加载)
				// computed: {
				// 	fullName: function() {
				// 		console.log("加载一次")
				// 		return this.firstName + " " + this.lastName;
				// 	}
				// }
			})
		</script>
	</body>
</html>

计算属性的get/set

控制台通过set修改属性,进行数据处理

代码语言:txt
复制

<!DOCTYPE html>

<html>

代码语言:txt
复制
<head>
代码语言:txt
复制
	<meta charset="utf-8">
代码语言:txt
复制
	<title>todoList</title>
代码语言:txt
复制
	<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
代码语言:txt
复制
</head>
代码语言:txt
复制
<body>
代码语言:txt
复制
	<div id="app">
代码语言:txt
复制
		<!-- 计算属性 触发无需加() -->
代码语言:txt
复制
		{{fullName}}
代码语言:txt
复制
		{{age}}
代码语言:txt
复制
	</div>
代码语言:txt
复制
	<script>
代码语言:txt
复制
		var app = new Vue({
代码语言:txt
复制
			el: '#app',
代码语言:txt
复制
			data: {
代码语言:txt
复制
				firstName: 'benny',
代码语言:txt
复制
				lastName: 'rhys',
代码语言:txt
复制
			},
代码语言:txt
复制
			//计算属性(缓存机制,所依赖的变量改变才重新加载)
代码语言:txt
复制
			computed: {
代码语言:txt
复制
				fullName: {
代码语言:txt
复制
					get: function() {
代码语言:txt
复制
						return this.firstName + " " + this.lastName;
代码语言:txt
复制
					},
代码语言:txt
复制
					set: function(value) {
代码语言:txt
复制
						var arr = value.split(" ");
代码语言:txt
复制
						this.firstName = arr[0];
代码语言:txt
复制
						this.lastName = arr[1];
代码语言:txt
复制
					}
代码语言:txt
复制
				}
代码语言:txt
复制
			}
代码语言:txt
复制
		})
代码语言:txt
复制
	</script>
代码语言:txt
复制
</body>

</html>

代码语言:txt
复制

样式

class的对象绑定 :class="{activated: isActivated}"

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<style>
			.activated {
				color: red;
			}
		</style>
	</head>
	<body>
		<div id="app">
			<div @click="handleDivClick"
				:class="{activated: isActivated}"
			>
				hello world
			</div>
			
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					isActivated: false
				},
				methods: {
					handleDivClick: function() {
						this.isActivated = !this.isActivated
					}
				}
			})
		</script>
	</body>
</html>

clss数组绑定(代表变量,可多变量)

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<style>
			.activated {
				color: red;
			}
		</style>
	</head>
	<body>
		<div id="app">
			<div @click="handleDivClick"
				:class="[activated, two]"
			>
				hello world
			</div>
			
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					activated: "",
					two: "two"
				},
				methods: {
					handleDivClick: function() {
						this.activated = this.activated === "activated" ? "" : this.activated="activated";
					}
				}
			})
		</script>
	</body>
</html>

Style按变量绑定 :style="styleObj"

或者数组 :style="styleObj, {fontSize: '20px'}"

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<div @click="handleDivClick"
				:style="[styleObj, {fontSize: '20px'}]"
			>
				hello world
			</div>
			
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					styleObj: {
						color: "black"
					}
				},
				methods: {
					handleDivClick: function() {
						this.styleObj.color = this.styleObj.color === "black" ? "red" : "black";
					}
				}
			})
		</script>
	</body>
</html>

条件语句

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 不显示在dom中也不存在
				 key值添加防止虚拟dom复用导致数据复用-->
			<div v-if="show === 'a'">v-if</div>
			<div v-else-if="show === 'b'">v-else-if</div>
			<div v-else >v-else</div>
			
			<!-- 及时不显示,在dom中存在。display: none; -->
			<div v-show="show">v-show</div>
			
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					show: "a"
				},
				methods: {
					
				}
			})
		</script>
	</body>
</html>

列表渲染

数组

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 
			修改直接同步数据的2种方式:1list.push、pop、re、 2指向的对象体
			不能同步的修改:指定数组下标赋值
			key值尽量不要用index,应该用后端传递的唯一id
			 template页面不显示
			 -->
			<template v-for="(item, index) of list" :key="item.id">
				<div>{{item.text}}---{{index}}</div>
				<span>{{item.text}}</span>
			</template>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					list: [
						{id: 1, text: "zhangsan"},
						{id: 2, text: "lisi"}
					]
				},
				methods: {
					
				}
			})
		</script>
	</body>
</html>

对象有key

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>todoList</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 
			同步更新:修改部分属性、修改指向
			不同步:增删
			bennyrhys--name--0 23--age--1 boy--gender--2
			 -->
			<template v-for="(key, item, index) of userInfo">
				{{key}}--{{item}}--{{index}}
			</template>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data: {
					userInfo: {
						name: "bennyrhys",
						age: 23,
						gender: "boy"
					}
				},
				methods: {
					
				}
			})
		</script>
	</body>
</html>

深入理解 Vue 组件

父子元素is配合组件 子组件返回data

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 父子关系的组件 is="row" 避免出现渲染bug -->
			<table>
				<tr is="row"></tr>
				<tr is="row"></tr>
				<tr is="row"></tr>
			</table>
		</div>
		<script>
			Vue.component('row', {
				// 子组件,data要写成函数,才能防止报错
				data: function() {
					return {
						content: 'this is row'
					}
				},
				template:'<tr><td>{{content}}</td></tr>'
			}) 
			var app = new Vue({
				el: '#app',
				
			})
		</script>
	</body>
</html>

标签ref引用的页面dom

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 标签使用ref,为了可以使用dom -->
			<div 
				ref="hello"
				@click="handleClick">
				hello
			</div>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				methods:{
					handleClick: function() {
						alert(this.$refs.hello.innerHTML)
					}
				}
				
			})
		</script>
	</body>
</html>

组件ref引用的是子组件的数据

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 组件使用ref,引用子组件的data -->
			<team ref="t1" @change="handleChange"></team>
			<team ref="t2" @change="handleChange"></team>
			<div>{{total}}</div>
		</div>
		<script>
			Vue.component('team', {
				data: function() {
					return {
						number: 0
					}
				},
				methods:{
					handleClick: function() {
						this.number ++
						// 子组件给父组件的时间触发,父组件需要接收绑定
						this.$emit('change')
					}
				},
				template: '<div @click="handleClick">{{number}}</div>'
			})
			var app = new Vue({
				el: '#app',
				data: {
					total: 0
				},
				methods:{
					handleChange: function() {
						this.total = this.$refs.t1.number + this.$refs.t2.number
					}
				}
				
			})
		</script>
	</body>
</html>

父子组件传值:

父->子

注意:单项数据流概念,(父传子,子不可修改父值。因为父值是基本类型还可以,但是引用类型的对象,可能修改之后会影响其他子组件)

解决:单项数据流。使用子组件变量保存

案例:子组件 两个数值

父<-子

案例:两个子组件的数值累加传出

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>父->子组价传值</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- 父->子属性传值
				:xxx="",表示传递js表达式
				xxx="",表示传递字符
			 -->
			<counter :count="3" @cin="handelCountAdd"></counter>
			<counter :count="2" @cin="handelCountAdd"></counter>
			<!-- 父<-子属性传值
				this.$emit('changeAdd', 1)
				@changeAdd="handelCountAdd"
			 -->
			 <div >{{total}}</div>
		</div>
		<script>
			var counter = {
				// 接收组件值
				props: ['count'],
				template: '<div @click="handleClick">{{number}}</div>',
				data: function(){
					return {
						number: this.count
					}
				},
				methods: {
					handleClick: function() {
						this.number = this.number + 1;
						this.$emit('cin', 1)
					}
				}
			}
			var app = new Vue({
				el: '#app',
				data: {
					total: 5
				},
				components:{
					// 将局部组件注册进实例
					counter: counter 
				},
				methods:{
					handelCountAdd: function(step) {
						this.total += step
					}
				}
			})
		</script>
	</body>
</html>

组件参数校验

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>组件参数校验非props特性</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<child count="xxxxxxxxxx"></child>
			<!-- <child :count="{a:1}"></child> -->
		</div>
		<script>
			Vue.component('child', {
				// props:[] 参数检测按照下面方法
				props: {
					// count: Number // 数值
					// count: [String, Number] // 数组
					count: {
						type: String,
						// required: false
						// default: 'xxx'
						validator:function(value) {
							return (value.length > 5)
						}
					}
				},
				template:'<div>{{count}}</div>'
			})
			var app = new Vue({
				el: '#app'
			})
		</script>
	</body>
</html>

非props特性

不可父组件传子组件值,标签会带有传值属性

props特性,父子属性值对接传递 标签没有属性

给组件绑定原生事件

通过子组件->组件 转两次触发

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>组件参数校验非props特性</title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<child @click="handleClick"></child>
		</div>
		<script>
			Vue.component('child', {
				template:'<div @click="handleClick">xxx</div>',
				methods:{
					handleClick: function() {
						alert("click click");
						this.$emit('click')
					}
				}
			})
			var app = new Vue({
				el: '#app',
				methods:{
					handleClick:function() {
						alert("click")
					}
				}
			})
		</script>
	</body>
</html>

组件上直接原生触发@click.native="handleClick"

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- <child @click="handleClick"></child> -->
			
			<child @click.native="handleClick"></child>
		</div>
		<script>
			Vue.component('child', {
				template:'<div,
				
				// template:'<div @click="handleClick">xxx</div>',
				// methods:{
				// 	handleClick: function() {
				// 		alert("click click");
				// 		this.$emit('click')
				// 	}
				// }
			})
			var app = new Vue({
				el: '#app',
				methods:{
					handleClick:function() {
						alert("click")
					}
				}
			})
		</script>
	</body>
</html>

非父子组件传值

image-20201121132041636
image-20201121132041636

解决非父子组件传值:

  • Vue官方提供了:VueX数据层框架
  • 发布订阅模式(总线机制/bus/观察者模式)

总线bus 定义 触发 生命周期赋值改变

案例:两个子组件数值,点击变成对方

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<child content="hello"></child>
			<child content="world"></child>
			
		</div>
		<script>
			// 非父子组件传值
			// 新增bus总线 装载新属性
			Vue.prototype.bus = new Vue()
			
			Vue.component('child', {
				props:{
					content: String
				},
				template:'<div @click="handleClick">{{selfContent}}</div>',
				// 单项数据流
				data: function() {
					return {
						selfContent: this.content
					}
				},
				methods:{
					handleClick: function() {
						// 通过bus子组件传值
						this.bus.$emit('change', this.selfContent)
					}
				},
				mounted: function(){
					// this作用域
					var this_ = this
					// $on监听
					this.bus.$on('change', function(msg) {
						// alert(msg) 
						// 两个子组件会被触发两次
						this_.selfContent = msg
					})
				}
			})
			var app = new Vue({
				el: '#app',
				methods:{
					
				}
			})
		</script>
	</body>
</html>

Vue中使用插槽

具名插槽slot

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<!-- 
			header
			www
			footer
		 -->
		<div id="app">
			<child>
				<div slot="header">header</div>
				<div slot="footer">footer</div>
			</child>
		</div>
		<script>
			Vue.component('child', {
				template:`<div>
							<slot name="header"></slot>
							<div>www</div>
							<slot name="footer"></slot>
						  </div>`
			})
			var app = new Vue({
				el: '#app',
				methods:{
					
				}
			})
		</script>
	</body>
</html>

Vue的作用域插槽

作用域组件必须template标签

场景:列表循环 样式父组件控制

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<child>
				<!-- 作用域组件必须template标签
				 1
				 2
				 3
				 4-->
				<template slot-scope="props">
					<h1>{{props.item}}</h1>
				</template>
			</child>
		</div>
		<script>
			Vue.component('child', {
				data:function() {
					return {
						list:[1, 2, 3, 4]
					}
				},
				// 子组件给父组件传递插槽的值
				template:`<div>
							<ul>
								<slot
									v-for="item of list"
									:item=item>
								</slot>
							</ul>
						  </div>`
			})
			var app = new Vue({
				el: '#app',
			})
		</script>
	</body>
</html>

动态组件v-once指令

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<!-- v-once通过缓存,解决创建并销毁的性能问题  -->
			<!-- <child1 v-if="type === 'child1'"></child1>
			<child2 v-if="type === 'child2'"></child2> -->
			
			<!-- 动态组件 -->
			<component :is="type"></component>
			
			<button @click="handleClick">点击切换显示</button>
		</div>
		<script>
			Vue.component('child1', {
				template:'<div v-once>a</div>'
			})
			Vue.component('child2', {
				template:'<div v-once>b</div>'
			})
			var app = new Vue({
				el: '#app',
				data:{
					type: "child1"
				},
				methods:{
					handleClick: function() {
						this.type = (this.type === "child1" ? "child2" : "child1")
					}
				}
			})
		</script>
	</body>
</html>

Vue 中的动画特效

Vue中的Css动画

动画出现

image-20201121222114671
image-20201121222114671

动画离开

image-20201121222142147
image-20201121222142147
代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<style>
			.fade-enter,
			.fade-leave-to{
				opacity: 0
			}
			.fade-enter-active,
			.fade-leave-active{
				transition: opacity 3s;
			}
		</style>
	</head>
	<body>
		<div id="app">
			<!-- 
				name绑定和上方样式.fade-对应。如果不起name则样式默认.v-
				动画过渡是监控opacity画面出现时为1,监控值变化则开始动画过渡3s
			 -->
			<transition name="fade">
				<div v-if="show">hello world</div>
			</transition>
			<button @click="handleClick">点击切换显示</button>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data:{
					show: true
				},
				methods:{
					handleClick: function() {
						this.show = !this.show
					}
				}
			})
		</script>
	</body>
</html>

Animate.css库

先由自定义c3动画效果引入animation

定义动画执行到%多少,文字放大多少倍

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<style>
			@keyframes bounce-in {
				0% {
					transform: scale(0);
				}
				50% {
					transform: scale(1.5);
				}
				100% {
					transform: scale(1);
				}
			}
			.fade-enter-active{
				transform-origin: left center;
				animation: bounce-in 1s;
			}
			.fade-leave-active{
				transform-origin: left center; 
				animation: bounce-in 1s reverse;
			}
		</style>
	</head>
	<body>
		<div id="app">
			<transition name="fade">
				<div v-if="show">hello world</div>
			</transition>
			<button @click="handleClick">点击切换显示</button>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data:{
					show: true
				},
				methods:{
					handleClick: function() {
						this.show = !this.show
					}
				}
			})
		</script>
	</body>
</html>

// 自定义css名
<style>
			.active{
				transform-origin: left center;
				animation: bounce-in 1s;
			}
			.leave{
				transform-origin: left center; 
				animation: bounce-in 1s reverse;
			}
</style>
			<transition 
				name="fade"
				enter-active-class="active"
				leave-active-class="leave">
				<div v-if="show">hello world</div>
			</transition>

开始Animate.css库

官网下载csshttps://animate.style/

引入link css路径

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<link
		    rel="stylesheet"
		    href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
		  />
	</head>
	<body>
		<div id="app">
			<transition 
				name="fade"
				enter-active-class="animate__animated animate__flash"
				leave-active-class="animate__animated animate__bounce"
        appear
				appear-active-class="animate__animated animate__bounce"
				>
				<div v-if="show">hello world</div>
			</transition>
			<button @click="handleClick">点击切换显示</button>

		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data:{
					show: true
				},
				methods:{
					handleClick: function() {
						this.show = !this.show
					}
				}
			})
		</script>
	</body>
</html>

Vue中同时使用过渡和动画

两种动画

  • 引入第三方库,使用的是@keyframes修饰的
  • 过渡动画transition

动画时长

  • 以哪个为准type指定type="transition"
  • 自定义手动设置:duration="10000"或者详细:duration="{enter: 5000, leave: 10000}"
代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<style>
			.fade-enter, .fade-leave-to {
				opacity: 0;
			}
			.fade-enter-active, .fade-leave-active {
				transition: opacity 3s; 
			}
		</style>
		<link
		    rel="stylesheet"
		    href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
		  />
	</head>
	<body>
		<div id="app">
			<transition 
				:duration="{enter: 5000, leave: 10000}"
				name="fade"
				appear
				enter-active-class="animate__animated animate__flash fade-enter-active"
				leave-active-class="animate__animated animate__bounce fade-leave-active"
				
				appear-active-class="animate__animated animate__bounce"
				>
				<div v-if="show">hello world</div>
			</transition>
			<button @click="handleClick">点击切换显示</button>

		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data:{
					show: true
				},
				methods:{
					handleClick: function() {
						this.show = !this.show
					}
				}
			})
		</script>
	</body>
</html>

Vue中的Js动画与Velocity.js结合

代码语言:txt
复制
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./vue.js" type="text/javascript" charset="utf-8"></script>
		<style>
			
		</style>
		<link
		    rel="stylesheet"
		    href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
		  />
	</head>
	<body>
		<div id="app">
			<!-- enter 换成 leave -->
			<transition 
				name="fade"
				@before-enter="handleBeforeEnter"
				@enter="handleEnter"
				@after-enter="handleAfterEnter"
				>
				<div v-if="show">hello world</div>
			</transition>
			<button @click="handleClick">点击切换显示</button>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data:{
					show: true
				},
				methods:{
					handleClick: function() {
						this.show = !this.show
					},
					handleBeforeEnter: function(el) {
						el.style.color = 'red'
					},
					handleEnter:function(el, done) {
						setTimeout(() => {
							el.style.color = 'green'
						}, 2000)
						setTimeout(() => {
							done()
						}, 4000)
					},
					handleAfterEnter: function(el) {
						el.style.color = "#000"
					}
				}
			})
		</script>
	</body>
</html>

http://velocityjs.org/#duration

引入velocity.js后钩子函数的简单使用

案例:结合上边点击出现的动画

image-20201122141203314
image-20201122141203314

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • dom和vue对比
    • Helloworld
      • 计时器对比
        • todoList练习
          • mvp对比MVVM
            • 组件化-todoList
              • Vue实例的生命周期钩子
                • Vue模板语法
                  • 计算属性、方法、监听
                    • 计算属性的get/set
                      • 样式
                        • 条件语句
                          • 列表渲染
                          • 深入理解 Vue 组件
                            • 父子元素is配合组件 子组件返回data
                              • 标签ref引用的页面dom
                                • 组件ref引用的是子组件的数据
                                  • 父子组件传值:
                                    • 组件参数校验
                                      • 非props特性
                                        • 给组件绑定原生事件
                                          • 非父子组件传值
                                            • Vue中使用插槽
                                              • Vue的作用域插槽
                                                • 动态组件v-once指令
                                                • Vue 中的动画特效
                                                  • Vue中的Css动画
                                                    • Animate.css库
                                                      • Vue中同时使用过渡和动画
                                                        • Vue中的Js动画与Velocity.js结合
                                                        领券
                                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档