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

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

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

toc

dom和vue对比

Helloworld

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

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

</html>

代码语言:txt
复制

样式

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

代码语言:txt
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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
AI代码解释
复制
<!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 删除。

评论
登录后参与评论
暂无评论
推荐阅读
使用PowerMockito如何对私有方法进行mock
我有一个publicMethod方法,在当中调用了privateMethod方法。
半月无霜
2024/07/15
1K0
junit4整合PowerMockito进行单元测试
所以我们在单测中,往往会使用mock的方式对这些代码做一个数据的模拟,从而达到对代码进行测试的一个目的。
半月无霜
2023/10/18
1.3K0
junit4整合PowerMockito进行单元测试
Java一分钟之-PowerMock:静态方法与私有方法测试
在Java单元测试的领域,PowerMock是一个扩展了Mockito功能的框架,它使得开发者能够模拟静态方法、构造函数、私有方法和final类,从而在测试中进一步隔离依赖项,达到更高的测试覆盖率。本文将深入浅出地介绍PowerMock的核心应用场景、常见问题、易错点以及如何避免这些问题,并通过实际代码示例加以说明。
Jimaks
2024/06/05
1.2K0
Java一分钟之-PowerMock:静态方法与私有方法测试
有了它(powerMocker)再也不怕单元测试不达标了!
目前应用比较普遍的java单元测试工具junit4+Mock(Mockito、jmock、EasyMock、powermock)。为什么会选powermock? 在做单元测试的时候,我们会发现我们要测试的方法会有很多外部依赖的对象或者一些其他服务的调用比如说(发送邮件,网络通讯,soa调用)。而我们没法控制这些外部依赖的对象。为了解决这个问题,我们需要用到Mock来模拟这些外部依赖的对象,从而控制它们。只关心我们自己的业务逻辑是否正确。而这时powermock就起作用了,它不仅可以mock外部的依赖,还可以mock私有方法、final方法,总之它的功能很强大。
java金融
2020/08/04
3.3K0
Mockito模拟进行单元测试
    MOCK意思是模拟的意思,主要被用来进行数据的人工组织,不会真正地调用第三方服务器,类似redis,mysql等都不会调用,也不用关心数据底层是如何进行处理的,我们要做的只是将本单元的逻辑进行单元测试,验证数据的逻辑处理性,而其中mock较好的框架就是Mockito。
chinotan
2019/07/15
9.7K0
Mockito模拟进行单元测试
SpringBootTest 和PowerMocker
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/135408.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/05
5070
告别加班/解放双手提高单测覆盖率之Java 自动生成单测代码神器推荐
很多公司对分支单测覆盖率会有一定的要求,比如 单测覆盖率要达到 60% 或者 80%才可以发布。
明明如月学长
2022/02/15
6.8K0
告别加班/解放双手提高单测覆盖率之Java 自动生成单测代码神器推荐
JAVA实战:如何让单元测试覆盖率达到80%甚至以上
单元测试(unit testing)是指对软件中的最小可测试单元进行检查和验证。它是软件测试中的一种基本方法,也是软件开发过程中的一个重要步骤。
你可以叫我老白
2023/03/21
4K1
JAVA实战:如何让单元测试覆盖率达到80%甚至以上
Mocktio 使用(下)
thenReturn 用来指定特定函数和参数调用的返回值。thenReturn 中可以指定多个返回值,在调用时返回值依次出现。若调用次数超过返回值的数量,再次调用时返回最后一个返回值。
HLee
2021/10/11
3.7K0
Mocktio 使用(下)
使用PowerMockito如何对私有方法进行单元测试
在上一篇文章中,讲解了公共方法调用私有方法的测试,我们只想对公共方法进行验证测试,私有方法进行mock即可
半月无霜
2024/07/16
8900
使用 Junit + Mockito 实践单元测试
相信做过开发的同学,都多多少少写过下面的代码,很长一段时间我一直以为这就是单元测试...
JMCui
2020/05/06
4.9K0
Spock框架Mock静态资源经验汇总
前面讲了Spock框架Mock对象、方法经验总结,今天分享一下Spock框架中Mock静态资源的实践经验汇总。分成「静态资源」和「混合场景」。
FunTester
2022/02/08
1.8K0
临时工 - PowerMock系列4
在测试过程中,发现我们的开发同学喜欢在方法中临时new 出一些类来完成某项工作。由于局部变量用完立即销毁了,使用起来也就非常灵活和随意了。 但这样就对单元测试造成了不小的麻烦。如以下的案例
Antony
2020/12/01
9330
Mockito和PowerMock用法
在单元测试中,我们往往想去独立地去测一个类中的某个方法,但是这个类可不是独立的,它会去调用一些其它类的方法和service,这也就导致了以下两个问题:外部服务可能无法在单元测试的环境中正常工作,因为它们可能需要访问数据库或者使用一些其它的外部系统。我们的测试关注点在于这个类的实现上,外部类的一些行为可能会影响到我们对本类的测试,那也就失去了我们进行单测的意义。
一滴水的眼泪
2020/09/24
3.3K0
使用PowerMock进行单元测试
单元测试可以提高测试开发的效率,减少代码错误率,提高代码健壮性,提高代码质量。在Spring框架中常用的两种测试框架:PowerMockRunner和SpringRunner两个单元测试,鉴于SpringRunner启动的一系列依赖和数据连接的问题,推荐使用PowerMockRunner,这样能有效的提高测试的效率,并且其提供的API能覆盖的场景广泛,使用方便,可谓是Java单元测试之模拟利器。
Dream城堡
2022/01/07
3.7K0
PowerMock(一):PowerMock的使用
现在流行的测试驱动开发TDD(Test-Driven Development) ,是敏捷开发中一项核心实践和技术。也是一种设计方法论。其中最重要的一环就是使用单元测试。单元测试是保证代码质量的一个重要手段,通过单元测试我们可以快速的测试代码的各个分支,各种场景,代码重构时只需要重新跑下单元测试就是能知道代码潜在的问题。单元测试是通过Mock的方式调用被测试的方法,其有如下几个优点:
码农飞哥
2021/08/18
8.1K0
EasyMock PowerMock 的简单使用(with spring Autowired)
<br />import java.math.BigDecimal;</p> <p>import org.easymock.EasyMock;<br />import org.junit.Assert;<br />import org.junit.Test;<br />import org.junit.runner.RunWith;<br />import org.powermock.api.easymock.PowerMock;<br />import org.powermock.core.classloader.annotations.PowerMockIgnore;<br />import org.powermock.core.classloader.annotations.PrepareForTest;<br />import org.powermock.modules.junit4.PowerMockRunner;<br />import org.springframework.aop.framework.Advised;<br />import org.springframework.beans.factory.annotation.Autowired;<br />import org.springframework.test.util.ReflectionTestUtils;</p> <p>@RunWith(PowerMockRunner.class)<br />@PrepareForTest( { PaymentReconService.class })<br />@PowerMockIgnore(“org.apache.log4j.*”)<br />public class PaymentGatherServiceTest extends PaymentServiceTestBase {</p> <p> @Autowired<br /> private GatherService gatherResultService;<br /> @Autowired<br /> private PaymentBaseDAO baseDAO;</p> <p> /**<br /> * 测试正常postback<br /> */<br /> public void testPaymentSucc() {<br /> PaymentReconService mock = mock();</p> <p> Long pbId = 10004L;<br /> String pbStatus = PaymentBaseEO.PB_STATUS_GATHER_SUCC;<br /> BigDecimal succAmount = new BigDecimal(“99.3”);</p> <p> try {<br /> GatherOrderRO ro = gatherResultService.processPaymentGather(pbId, pbStatus, succAmount, succAmount);<br /> assertNotNull(ro);</p> <p> } catch (SystemException e) {<br /> fail(e.getLocalizedMessage());<br /> } catch (BusinessException e) {<br /> fail(e.getBusinessCode());<br /> }<br /> EasyMock.verify(mock);<br /> }</p> <p> /**<br /> * MOCK PaymentReconService实现<br /> * @return<br /> */<br /> private PaymentReconService mock() {<br /> PaymentReconRO mockRO = new PaymentReconRO(PaymentReconRO.Status.SUCESS, “OK”);</p> <p> PaymentReconService mock = EasyMock.createMock(PaymentReconServiceImpl.class);<br /> EasyMock.expect(mock.paymentSuccessRecon(EasyMock.anyObject(Long.class))).andReturn(mockRO);<br /> EasyMock.replay(mock);<br /> //这里把依赖的数据注进去<br /> ReflectionTestUtils.s
全栈程序员站长
2021/05/19
7100
powermockito教程_SpringBoot使用Powermockito单元测试
mockito框架上手非常简单,但是它也有弊端和局限性,不能mock静态方法、私有方法、构造方法等,但powermockito框架很好的弥补了这一缺陷。
全栈程序员站长
2022/11/17
1.9K0
代码整洁之道-读书笔记之单元测试
TDD:测试驱动开发,先写测试,再写逻辑代码,通过单测,写逻辑代码,依次循环,知道所有逻辑都完成
特特
2022/11/16
6360
Java 数据分批调用接口的正确姿势
现实业务开发中,通常为了避免超时、对方接口限制等原因需要对支持批量的接口的数据分批调用。
明明如月学长
2021/08/31
2K0
推荐阅读
相关推荐
使用PowerMockito如何对私有方法进行mock
更多 >
LV.4
上海顶简软件Java开发工程师
目录
  • 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 归档