前端框架Vue:基本指令、事件、分支循环、计算属性、侦听器、过滤器、生命周期

Vue

最近浏览码云上的热门项目,发现很多前端框架都是基于Vue的,作为一名合格的后端开发人员,应该静下心来好好学习一下。争取日后将公司的笨重项目前后端分离,升级重构一波,从被jsp、jquery支配的恐惧中解放出来!

一、Vue简单指令

1、入门 Hello World
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<div>{{msg}}</div>
			<div>{{1+2}}</div>
			<div>{{msg +'--------'+123}}</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue'
				}
			});
		</script>
	</body>
</html>

2、v-cloak指令

可以解决插值闪动的问题

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		<style type="text/css">
			[v-cloak]{
				display: none;
			}
		</style>
	</head>
	<body>
		<!--v-cloak用于解决闪动问题,
			先通过样式隐藏内容,然后在内存中进行值的替换,
			替换好之后显示最终的结果
		 -->
		<div id="app">
			<div v-cloak>  <!-- v-cloak-->
				{{msg}}
			</div>

		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue'
				}
			});
		</script>
	</body>
</html>

3、v-text指令

填充纯文本

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<div v-text="msg"></div> <!-- 直接引用data中的数据-->
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue'
				}
			});
		</script>
	</body>
</html>

4、v-html指令

解析

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		
	</head>
	<body>
		<!-- 注意:v-hmtl指令存在安全隐患,慎用 -->
		<div id="app">
			<div v-text="msg"></div>
			<div v-html="msg1"></div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue',
					msg1:'<h1>vue</h1>'
				}
			});
		</script>
	</body>
</html>

5、v-pre指令

跳过编译

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		
	</head>
	<body>
		<!-- v-pre 显示原始的信息,跳过编译过程 -->
		<div id="app">
			<div v-pre>{{msg}}</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue',
					msg1:'<h1>vue</h1>'
				}
			});
		</script>
	</body>
</html>

6、v-once指令

数据响应式相关

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		
	</head>
	<body>
		
		<!-- v-once只渲染一次,
			如果显示的信息后续不需要再修改,可以使用v-once
			可以提高性能

		后面的msg的值如果修改了,渲染的值不变
		 -->
		<div id="app">
			<div v-once>{{msg}}</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue',
					msg1:'<h1>vue</h1>'
				}
			});
		</script>
	</body>
</html>

7、v-model指令

实现双向数据绑定

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<!-- v-model绑定msg,实现动态变化
			input输入框中值的变化会引起msg的变化
		-->
		<div id="app">
			<div>{{msg}}</div>
			<input type="text" v-model="msg" />
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue',
					msg1:'<h1>vue</h1>'
				}
			});
		</script>
	</body>
</html>

二、Vue事件指令

1、v-on指令
绑定事件
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<!-- v-on 事件绑定
			简写 @click
		 -->
		<div id="app">
			<div>{{num}}</div>
			<button type="button" v-on:click="num++">点击1</button>
			<!-- 方法的调用可以加() -->
			<button type="button" @click="fun1">点击2</button>
			<button type="button" @click="fun1()">点击3</button>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					num:0
				},
				methods:{ //方法必须定义在methods这个属性当中
					fun1:function(){
						//这里的this其实是vue的实例对象vm
						this.num++;
					}
				}
			});
		</script>
	</body>
</html>

2、事件绑定的参数传递

使用函数名以及函数名()调用方法的区别与规则

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<!-- 
			1、如果事件直接绑定函数名字,那么默认会传递事件对象作为事件函数的第一个参数
			2、如果事件绑定函数调用(),那么事件对象就是最后一个参数,名称是 $event
			这是这两种方式的区别
		 -->
		<div id="app">
			<button type="button" @click="fun1">点击1</button>
			<button type="button" @click="fun2(1,2,$event)">点击2</button>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					num:0
				},
				methods:{ 
					fun1:function(event){
						console.log(event.target.innerHTML)
					},
					fun2:function(x,y,event){
						console.log(x,y)
						console.log(event.target.innerHTML)
					}
				}
			});
		</script>
	</body>
</html>

3、事件修饰符
  • .stop 可以阻止事件冒泡行为
  • .prevent 可以阻止默认行为
  • 其他的事件修饰符参考官方文档
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<!-- 事件冒泡的发生,我点击的是里面的div,但是还是调用了fun1
		 解决办法使用stop
		 -->
		<div id="app">
			<div >{{num}}</div>
			<div v-on:click="fun1">
				<!-- 使用stop修饰符阻止冒泡 -->
				<button type="button" @click.stop="fun2">点击</button>
			</div>
			<!-- 使用prevent防止跳转到百度页面 -->
			<a href="http://www.baidu.com" @click.prevent="fun3">百度一下</a>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					num:1
				},
				methods:{ 
					fun1:function(){
						this.num++
					},
					fun2:function(){
						console.log("hehe")
					},
					fun3:function(){
						console.log("点击了")
					}
				}
			});
		</script>
	</body>
</html>

4、按键事件修饰符
  • .enter 回车键
  • .delete 删除键
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		
		<div id="app">
			<!-- 这里绑定一个删除键的修饰符 -->
			用户名:<input type="text" v-model="uname" @keydown.delete="clearContent" /> <br />
			<!-- 这里绑定一个回车键的修饰符 @keydown.enter -->
			密码:<input type="text" v-model="password" @keydown.enter="submit"/><br />
			<button type="button" @click="submit">登入</button>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					uname:'pihao',
					password:'123456'
				},
				methods:{ 
					submit:function(){
						alert("登入成功")
					},
					clearContent:function(){
						this.uname=''
						this.password=''
					}
				}
			});
		</script>
	</body>
</html>

5、属性绑定

v-bind 用于绑定html标签的属性

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<!-- v-bind 可以绑定html标签的属性 -->
			<a v-bind:href="url">百度一下</a>
			<button type="button" @click="change">切换</button>
			<!-- v-bind也可以简写 -->
			<a :href="url">百度一下2</a>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					url:'http://www.baidu.com'
				},
				methods:{
					//修改url地址
					change:function(){
						this.url='http://taobao.com'
					}
				}
			});
		</script>
	</body>
</html>

使用v-bind和事件监听实现数据的双向绑定

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<!-- v-bind 可以绑定html标签的属性 -->
			<a v-bind:href="url">百度一下</a>
			<button type="button" @click="change">切换</button>
			<!-- v-bind也可以简写 -->
			<a :href="url">百度一下2</a>
			
			<hr >
			<!-- 使用v-bind 与事件监听来实现v-model数据双向绑定 -->
			{{msg}} <br>
			<input type="text" v-bind:value="msg" v-on:input="handle" /> <br>
			<input type="text" v-bind:value="msg" v-on:input="msg=$event.target.value" /><br>
			<input type="text" v-model="msg" />
			
		</div>
		
		
		
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					url:'http://www.baidu.com',
					msg:'hello vue'
				},
				methods:{
					//修改url地址
					change:function(){
						this.url='http://taobao.com'
					},
					handle:function(event){
						this.msg = event.target.value
					}
				}
			});
		</script>
	</body>
</html>

6、样式绑定

通过vue来控制CSS的样式

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		<style type="text/css">
			.active {
				border: 1px solid deeppink;
				width: 100px;
				height: 100px;
			}
			.error {
				background-color: orange;
			}
		</style>
	</head>
	<body>
		
		<div id="app">
			<!-- 绑定class属性,对象的规则 -->
			<div v-bind:class="{active:isActive,error:isError}">测试1</div>
			<button type="button" @click="change">切换</button>
			<!-- 绑定class属性,数组的规则 -->
			<div v-bind:class="[activeClass,errorClass]">测试2</div>
			<button type="button" @click="handle">切换</button>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					isActive:true,
					isError:true,
					activeClass:'active',
					errorClass:'error'
				},
				methods:{
					change:function(){
						//控制isActive的值在true和false之间切换
						this.isActive = !this.isActive
						this.isError = !this.isError
					},
					handle:function(){
						this.errorClass=''
					}
				}
			});
		</script>
	</body>
</html>

7、style样式处理

其实就是v-bind绑定style属性

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		
	</head>
	<body>
		
		<div id="app"> 
			<!-- 直接绑定style -->
			<div :style="styleObj"></div>
			<button type="button" @click="change">change</button>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					styleObj:{
						border:'1px solid pink',
						width:'200px',
						height:'100px'
					}
				},
				methods:{
					change:function(){
						this.styleObj.width='100px'
					}
				}
			});
		</script>
	</body>
</html>

三、分支循环结构

1、分支结构
  • v-if
  • v-else-if
  • v-else
  • v-show
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<div v-if="score >= 90">优秀</div>
			<div v-else-if="score < 90 && socre >= 80">良好</div>
			<div v-else-if="score < 80 && score >=60 ">及格</div>
			<div v-else>不及格</div>
			
			<!-- 
				v-if 和 v-show的区别
				v-if控制元素是否渲染到页面
				v-show控制元素是否显示(已经渲染到页面上)
			-->
			<div v-show="flag">测试v-show</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					score:30,
					flag:false
				}
			});
		</script>
	</body>
</html>

2、循环结构
  • v-for遍历数组
  • key的作用:帮助Vue区分不同的元素,从而提高性能
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<li v-for="item in fruits">{{item}}</li>
			<!-- item和key都是自定义的名字 -->
			<li v-for="(item,key) in fruits">{{item +'-----' +key}}</li>
			<!-- 绑定的key的属性一般是唯一的id -->
			<li :key='item.id' v-for="item in myFruits">{{item.cname +'------'+ item.ename}}</li>
			<!-- 对象的遍历 (值,键,索引)-->
			<li v-for="(value,key,index) in obj">{{key+"--------"+value+"--------"+index}}</li>
			<hr>
			<!-- 还能与v-if结合使用 -->
			<li v-if="value==24" v-for="(value,key,index) in obj">{{key+"--------"+value+"--------"+index}}</li>
			
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					fruits:['apple','orange','banana'],
					myFruits:[{
						id:1,
						ename:'apple',
						cname:'苹果'
					},{
						id:2,
						ename:'orange',
						cname:'橙子'
					},{
						id:3,
						ename:'banana',
						cname:'香蕉'
					}],
					obj:{
						name:'张三',
						gender:'male',
						age:24
					}
				}
				
			});
		</script>
	</body>
</html>

四、Vue常用特性

  • 表单操作
  • 自定义指令
  • 计算属性
  • 过滤器
  • 侦听器
  • 生命周期
1、表单操作
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		<div id="app">
			<form action="http://www.baidu.com">
				<div>
					<span>姓名:</span>
					<span>
						<input type="text" v-model="uname" />
					</span>
				</div>
				<div>
					<span>性别:</span>
					<span>
						<input type="radio" id="male" value=1 v-model="gender"/>
						<label for="male"></label>
						<input type="radio" id="female" value=0 v-model="gender"/>
						<label for="female"></label>
					</span>
				</div>
				<div>
					<span>爱好:</span>
					<span>
						<input type="checkbox" id="ball" value=1 v-model="hobby"/>
						<label for="ball">篮球</label>
						<input type="checkbox" id="sing" value=2 v-model="hobby"/>
						<label for="sing">唱歌</label>
						<input type="checkbox" id="code" value=3 v-model="hobby"/>
						<label for="code">写代码</label>
					</span>
				</div>
				<div>
					<span>职业:</span>
					<select v-model="occupation">
						<option value="0">请选择职业:</option>
						<option value="1">java开发工程师</option>
						<option value="2">测试工程师</option>
						<option value="3">运维工程师</option>
					</select>
				</div>
				<div>
					<span>个人简介:</span>
					<!-- <textarea v-model="description"></textarea> -->
					<textarea v-text="description"></textarea><!-- 这种方式就没有双向绑定 -->
				</div>
				<div id="">
					<!-- 防止跳转到页面 -->
					<input type="submit"  value="提交" @click.prevent="handle"/>
				</div>
			</form>
		</div>
		
		
		<script type="text/javascript">
			var vm = new Vue({
				el:"#app",
				data:{
					uname:'皮浩',
					gender:1,
					hobby:[2,3],
					occupation:'1',
					description:"你好啊"
				},
				methods:{
					handle:function(){
						console.log("执行了,并且使用了prevent默认跳转")
						console.log("gender是: "+ this.gender)
						console.log("hobby是:"+this.hobby.toString())
						console.log("occupation是:"+this.occupation)
						console.log(this.description)
					}
				}
			})
		</script>
	</body>
</html>

表单操作里面还有一个表单域修饰符

  • number:转化为数值
  • trim:去掉开始和末尾的空格
  • lazy:将input事件切换为change事件,失去焦点才会触发
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<!-- number修饰符,将字符串转化为数字 -->
			<input type="text" v-model.number="age" />
			<!-- trim修饰符,取出首尾的空格 -->
			<input type="text" v-model.trim="info" />
			<!-- lazy 将input事件切换为change事件
				 简单的说就是失去焦点的时候才会触发,
				 而input事件是值变化了就会触发
			 -->
			<div>{{msg}}</div>
			<input type="text"  v-model.lazy="msg"/>
			<button type="button" @click="handle">点击</button>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					age:'',
					info:'',
					msg:''
				},
				methods:{
					handle:function(){
						// console.log(this.age+1000)
						console.log(this.info.length)
					}
				}
			});
		</script>
	</body>
</html>

2、自定义指令

Vue内置的指令不满足需求的时候,我们可以自定义指令

内置指令语法规则

# 不带参数的 v-focus
Vue.directive('focus',{ 
                //这里的inserted是固定写法,具体看官网介绍
				inserted:function(el){
					//获取元素的焦点
					el.focus();
				}
			})
# 带参数的  v-color='msg'
Vue.directive('color',{
				inserted:function(el,binding){
					//打印binding,发现value属性才是我们想要的值
					console.log(binding.value) // pink,在vue的data中的值 msg:‘pink’
					//设置背景色
					el.style.backgroundColor=binding.value
					
				}
			})

实例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">

			<input type="text" v-focus/> 
			<input type="text" v-color="msg"/>
		</div>
		
		<script type="text/javascript">
			/* 自定义指令,不带参数 */
			Vue.directive('focus',{ 
				inserted:function(el){
					//获取元素的焦点
					el.focus();
				}
			})
			/* 自定义指令,带参数 */
			Vue.directive('color',{
				inserted:function(el,binding){
					//打印binding,发现value属性才是我们想要的值
					console.log(binding.value) // pink
					//设置背景色
					el.style.backgroundColor=binding.value
					
				}
			})
			 
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'deeppink'
				}
			});
		</script>
	</body>
</html>

局部指令的写法

directive,其实这种写法还更容易接受,就跟data、methods一样

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<input type="text" v-color="msg"/>
		</div>
		
		<script type="text/javascript">

			var vm = new Vue({
				el: '#app',
				data:{
					msg:'pink'
				},
				/* 局部指令,把指令当做组件注册到vue中 ,之前的那种写法是全局指令*/
				directives:{
					color:{
						inserted:function(el,binding){
							el.style.backgroundColor=binding.value
						}
					}
				}
			});
		</script>
	</body>
</html>

3、计算属性

为何引入计算属性呢?表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简洁,渲染的效率更高

简单的说,计算属性就是基于data中的数据来操作的

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<div>{{msg}}</div>
			<!-- 现在有一个需求,就是想要反转msg的内容显示 -->
			<div>{{msg.split('').reverse().join('')}}</div>
			<!-- 使用插值表达式,虽然也可以做到,但是可读性不好,在这里可以
			 使用计算属性来做到 -->
			 <div>{{reverseMsg}}</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue 123'
				},
				//计算属性,要有返回值
				computed:{
					reverseMsg:function(){
						return this.msg.split("").reverse().join("");
					}
				}
			});
		</script>
	</body>
</html>

我们发现计算属性和方法是非常类似的,那么两者有什么区别呢?

  • 计算属性是基于它们的依赖进行缓存的
  • 方法不存在缓存
4、侦听器

侦听器用于监视绑定的数据,数据一旦发生变化就通知侦听器所绑定的方法

使用场景:数据变化时执行异步或者开销大的操作

基本使用

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<div>
				<span>姓:</span>
				<span>
					<input type="text" v-model="firstName" />
				</span>
			</div>
			<div>
					<span>名:</span>
					<span>
						<input type="text" v-model="lastName" />
					</span>
			</div>
			
			<div>全名:{{fullName}}</div>
			<!-- ok.现在需求是当firstName或者lastName数据发生变化的时候fullName跟着变化 -->
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					firstName:'pi',
					lastName:'hao',
					fullName:'pi hao'
				},
				/* 监听 ,一单监听的值发生变化那么就会触发下面的动作*/
				watch:{
					//firstName和上面的属性一致,这里的var就是变化后的最新的值
					firstName:function(val){
						this.fullName = val + " " +this.lastName;
					},
					lastName:function(val){
						this.fullName = this.firstName+ " " +val;
					}
				},
				/* 其实通过计算属性也能完成上面的需求 */
				computed:{
					//{{allName}}即可
					allName:function(){
						return this.firstName+" " +this.lastName;
					}
				}
			});
		</script>
	</body>
</html>

侦听器的综合小案例

做一个登入校验的案例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SFj8Rare-1606405256099)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201126224203307.png)]

  • 通过v-model实现数据绑定
  • 需要提供提示信息
  • 需要通过侦听器监听输入的变化
  • 需要修改触发的事件(失去焦点才触发)
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<span><input type="text" v-model.lazy="uname" /></span>
			<span>{{tip}}</span>
		</div>
		
		<script type="text/javascript">
			/* 
			 1、采用侦听器监听用户名的变化
			 2、调用后台接口进行验证
			 3、根据验证的结果调整提示信息
			 */
			var vm = new Vue({
				el: '#app',
				data:{
					uname:'',
					tip:''
				},
				methods:{
					checkName:function(uname){
						//调用接口,但是可以使用定时任务的方式模拟接口调用
						var that = this; //在setTimeout中的this是window对象
						setTimeout(function(){
							//模拟接口调用
							if(uname == 'admin'){
								that.tip = "用户名已经存在,请更换一个";
							}else{
								that.tip='用户名可以使用'
							}
							
						},2000)
					}
				},
				watch:{
					uname:function(val){
						//调用后台接口验证用户名的合法性
						this.checkName(val)
						//修改提示信息
						this.tip="正在验证..."
					}
				}
			});
		</script>
	</body>
</html>

5、过滤器

Vue中的过滤器主要是用于格式化数据,比如将字符串首字母大写,将日期格式化为指定的格式等等

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<input type="text" v-model="msg" />
			<div >{{msg | upper}}</div>
			<div >{{msg | upper | toLower}}</div> <!-- 多级过滤-->
			<!-- 还能在绑定属性中使用 -->
			<div v-bind:id="msg | toUpper" >测试</div> <!-- 发现id = 'Hello'-->
		</div>
		
		<script type="text/javascript">
			/**
			 * 过滤器,全局定义
			 */
			Vue.filter('toUpper',function(val){
				//将首字母大写
				return val.charAt(0).toUpperCase() + val.slice(1)
			})
			//过滤器也支持级联操作,将前一个过滤器的结果再进行一次过滤
			Vue.filter('toLower',function(val){
				//将首字母大写
				return val.charAt(0).toLowerCase()+val.slice(1)
			})
			
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'hello'
				},
				//过滤器也支持局部定义
				filters:{
					upper:function(val){
						return val.charAt(0).toUpperCase()+val.slice(1);
					}
				}
			});
		</script>
	</body>
</html>

带参数的过滤器

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<div>{{date}}</div>
			<div>{{date | format('yyyy-MM-dd')}}</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue',
					date: new Date()
				},
				filters:{
					//使用过滤器格式化时间,从第二个参数开始接收 yyyy-MM-dd
					format:function(val,arg){
						if(arg == 'yyyy-MM-dd'){
							var ret = '';
							ret += val.getFullYear()+"-"+(val.getMonth()+1)+"-"+val.getDate();
							return ret;
						}
					}
				}
			});
		</script>
	</body>
</html>

五、生命周期

详细见官网

  • 主要阶段
    • 挂载(初始化相关属性)
      • beforeCreate
      • created 在实例创建完之后被立即调用
      • beforeMount
      • mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子,用的最多
    • 更新(元素或组件变更操作)
      • beforeUpdate
      • updated
    • 销毁(销毁相关属性)
      • beforeDestroy
      • destroyed

六、综合案例

补充知识(数组相关API)

1、变异方法(修改原有数据)响应式
  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
2、替换数组(生成新的数组) 需要重新赋值给data中元素
  • filter()
  • concat()
  • slice()
3、修改响应式数据
  • Vue.set(属性名,索引,新值)
  • vm.$set(属性名,索引,新值)
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
	</head>
	<body>
		
		<div id="app">
			<li v-for="item in list">{{item}}</li>
			<hr >
			<div>{{info.name}}</div>
			<div>{{info.age}}</div>
			<div>{{info.gender}}</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					msg:'Hello Vue',
					list:['apple','orange','strobery'],
					info:{
						name:'zhangsan',
						age:24
					}
				}
			});
			
			/**
			 * 修改值操作
			 */
			// vm.list[1]='change'; 该种操作不会立即渲染到页面上
			// Vue.set(vm.list,1,'change'); 
			// vm.$set(vm.list,0,'hello');
			
			//为info增加一个gender属性
			// vm.info.gender='male'; //不会立即渲染到页面上
			// Vue.set(vm.info,'gender','male');
			vm.$set(vm.info,'gender','male')
		</script>
	</body>
</html>

图书管理综合案例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
		<style type="text/css">
			.grid{
				margin: auto;
				width: 500px;
				text-align: center;
			}
			.grid table{
				width: 100%;
				border-collapse: collapse;
			}
			.grid th,td{
				padding: 10;
				border: 1px dashed orange;
				height: 35px;
				line-height: 35px;
				
			}
			.grid th{
				background-color: orange;
			}
			.grid .book{
				padding-bottom: 10px;
				padding-top: 5px;
				background-color: #F3DCAB;
			}
			.grid .total{
				height: 30px;
				line-height: 30px;
				background-color: hotpink;
			}
		</style>
	</head>
	<body>
		
		<div id="app">
			<div class="grid">
				<div>
					<h1>图书管理</h1>
					<div class="book">
						<div>
							<label for="id">
								编号:
							</label>
							<input type="text" id="id" v-model="id" style="width: 30%" :disabled="flag" v-focus/>
							<label for="name">
								名称:
							</label>
							<input type="text" id="name" v-model="name" style="width: 30%"/>
							<!-- 这里的禁用是为了输入相同的书名的时候,不允许添加 -->
							<button type="button" @click="handel" :disabled="btnFlag">提交</button>
						</div>
						
					</div>
				</div>
				<div class="total">
					<span>总数:{{sum}}</span>
				</div>
				<table >
					<thead>
						<tr>
							<th>编号</th>
							<th>名称</th>
							<th>时间</th>
							<th>操作</th>
						</tr>
					</thead>
					<tbody>
						<tr :key='item.id' v-for='item in books'>
							<td>{{item.id}}</td>
							<td>{{item.name}}</td>
							<td>{{item.date | format('yyyy-MM-dd')}}</td>
							<td>
								<a href="#" @click.prevent="toEdit(item.id)">修改</a>
								<span>|</span>
								<a href="#" @click.prevent="deleteBook(item.id)">删除</a>
							</td>
						</tr>
						
					</tbody>
					
				</table>
			</div>
		</div>
		
		<script type="text/javascript">
			var vm = new Vue({
				el: '#app',
				data:{
					id:'',
					name:'',
					flag:false,
					btnFlag:false,
					books:[]
				},
				computed:{
					sum:function(){
						//计算图书的总数
						return this.books.length;
					}
				},
				methods:{
					handel:function(){
						//该方法其实可以与编辑图书重用
						if(this.flag){
							//编辑图书
							//根据当前的id去更新数组中的数据,这里的箭头函数中的this就是vue实例的this
							this.books.some((item) => {
								if(item.id == this.id){
									item.name = this.name;
									//完成更新操作之后需要终止循环
									return true;
								}
							});
							this.flag = false;
							
						}else{
							//添加图书
							var book = {};
							book.id = this.id;
							book.name = this.name;
							book.date = new Date();
							this.books.push(book)
							//最后再清空表单
							this.id = '';
							this.name = '';
						}
						this.id = '';
						this.name = '';
					},
					toEdit:function(id){
						//根据id查询要编辑的数据,可以使用过滤器(这里的book获取到的是一个数组)
						var book = this.books.filter(function(item){
							return item.id == id
						});
						console.log(book);
						//把获取到的信息填充到表单
						this.id = book[0].id;
						//禁止修改id
						this.flag = true;
						this.name = book[0].name
							
					},
					deleteBook:function(id){
						//删除图书
						//先根据id找到索引
						// var index = this.books.findIndex(function(item){
						// 	return item.id == id;
						// })
						//根据索引删除图书
						// this.books.splice(index,1);
						//-----------------方法2--filter-----------
						this.books = this.books.filter(function(item){
							return item.id != id;
						})
					}
				},
				filters:{
					format:function(val,pattern){
						if(pattern == 'yyyy-MM-dd'){
							return val.getFullYear()+"-"+(val.getMonth()+1)+"-"+val.getDate();
						}
					}
				},
				directives:{
					focus:{
						inserted:function(el){
							el.focus()
						}
					}
				},
				watch:{
					name:function(val){
						//验证图书名称是否已经存在
						var flag = this.books.some(function(item){
							return item.name == val;
						})
						if(flag){
							//图书名称已经存在
							if(!flag){
								this.btnFlag = true;
							}
						}
					}
				},
				
				mounted:function(){
					//该生命周期钩子函数被触发的时候,模板已经可以使用了
					//一般此时用于调用接口获取后台数据,然后把数据填充到模板
					var data = [{
						id:1,
						name:'三国演义',
						date:new Date()
					},
					{
						id:2,
						name:'西游记',
						date:new Date()
					},
					{
						id:3,
						name:'红楼梦',
						date:new Date()
					}];
					
					this.books = data;
				}
			});
		</script>
	</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值