Vue基础4
- 计算属性
- 姓名案例 - 第一种用@click.keyup的方法
- 姓名案例 - 第二种用v-model双向绑定的方法
- 姓名案例 - 第三种使用methods方法
- 姓名案例 - 第四种使用计算属性的方法
- 计算属性的简写—只考虑读取,不考虑修改时候使用
- 监视属性
- 第一种普通写法
- 第二种用计算属性的写法
- 加上控制台输出
- 没有控制台输出
- 第三种用监视属性写
- 监视属性
- 监视属性第一种写法
- 监视属性第二种写法
- 深度监视
- 监视属性简写
- 监视属性第一种方式简写
- 监视属性第二种方式简写
- watch与computed对比
- 姓名案例-使用监视属性写
- 姓名案例-1s之后再显示
- 监视属性
- 计算属性
- 总结:computed和watch之间的区别
计算属性
姓名案例 - 第一种用@click.keyup的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div>姓:<input type="text" @keyup="showMsg"></div>
<div>名:<input type="text" @keyup="showTip"></div>
<div>
全名:
<span class="xing">{{lastName}}</span>
<span>-</span>
<span class="ming">{{firstName}}</span>
</div>
</div>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#app",
data:{
lastName:"",
firstName:""
},
methods:{
showMsg(e){
console.log(e.target.value)
this.lastName=e.target.value
},
showTip(e){
console.log(e.target.value)
this.firstName=e.target.value
}
}
})
</script>
</body>
</html>
姓名案例 - 第二种用v-model双向绑定的方法
并限制姓的长度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div id="root">
姓:<input type="text" v-model="lastName"> <br><br>
名:<input type="text" v-model="firstName"> <br><br>
全名:{{lastName.slice(0,3)}}-{{firstName}}
</div>
</div>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#app",
data:{
lastName:"张",
firstName:"三"
},
})
</script>
</body>
</html>
不满足插值语法的简洁要求
姓名案例 - 第三种使用methods方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<div id="root">
姓:<input type="text" v-model="lastName"> <br><br>
名:<input type="text" v-model="firstName"> <br><br>
<!-- 不使用括号调的是方法,使用括号调的是方法的返回值-->
全名:{{fullName()}}
</div>
</div>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#app",
data:{
lastName:"张",
firstName:"三"
},
methods:{
fullName(){
return this.lastName+"-"+this.firstName
}
}
})
</script>
</body>
</html>
姓名案例 - 第四种使用计算属性的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>姓名案例-计算属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="lastName"> <br><br>
名:<input type="text" v-model="firstName"> <br><br>
全名:{{fullName}} <br><br>
全名:{{fullName}} <br><br>
全名:{{fullName}} <br><br>
</div>
<script>
Vue.config.productionTip=false;
const vm=new Vue({
el:"#app",
data:{
lastName:"张",
firstName:"三"
},
computed:{
fullName:{
get(){
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.读取fullName时候 2.所依赖的数据发生变化时候
console.log("get被调用了~~~~")
let fullname=this.lastName.slice(0,3)+"-"+this.firstName.slice(0,3)
return fullname
},
set(value){
//set什么时候调用?当fullName被修改时
//value="张-三"
let arr=value.split("-")
this.lastName=arr[0]
this.firstName=arr[1]
}
}
}
})
</script>
</body>
</html>
计算属性:
- 定义:要用的属性不存在,要通过已有属性计算得来
- 原理:底层借助了Object.defineproperty方法提供的getter和setter。
- get函数什么时候执行
(1)初次读取的时候会执行一次
(2)当依赖的数据发生改变时会被再次调用 - 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
- 备注:
(1)计算属性最终会出现在vm上,直接读取使用即可
(2)如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生
计算属性的简写—只考虑读取,不考虑修改时候使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>姓名案例-计算属性的简写</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="lastName"> <br><br>
名: <input type="text" v-model="firstName"> <br><br>
全名:{{fullName}}
</div>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#root",
data:{
lastName:"张",
firstName:"三"
},
computed:{
fullName(){
console.log("get被调用了~~~")
return this.lastName+"-"+this.firstName
}
}
})
</script>
</body>
</html>
千万不能将fullName理解成函数调用,fullName是vm的属性
监视属性
第一种普通写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监视属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气很{{isActive?cool:hot}}</h1>
<button @click="toggleWeather">切换天气</button>
</div>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#root",
data:{
cool:"凉爽",
isActive:true,
hot:"炎热"
},
methods:{
toggleWeather(){
console.log("天气变化了,现在是:"+(this.isActive?this.hot:this.cool)+",原来是"+(this.isActive?this.cool:this.hot))
this.isActive=!this.isActive
}
}
})
</script>
</body>
</html>
第二种用计算属性的写法
加上控制台输出
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>天气案例</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气很{{weather}}</h1>
<button @click="toggleWeather">切换天气</button>
</div>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#root",
data:{
isHot:true
},
computed:{
weather(){
return this.isHot?"炎热":"凉爽"
}
},
methods:{
toggleWeather(){
console.log("天气变化了,现在是:"+(this.isHot?"凉爽":"炎热")+",原来是"+(this.isHot?"炎热":"凉爽"))
this.isHot=!this.isHot
}
}
})
</script>
</body>
</html>
没有控制台输出
在绑定事件时候,@xxx=“yyy” ,调用函数是一个语句时候,yyy可以直接写成语句
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>天气案例</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>今天天气很{{info}}</h1>
<!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句-->
<button @click="isHot=!isHot">切换天气</button>
</div>
<script>
Vue.config.productionTip=false;
new Vue({
el:"#app",
data:{
isHot:true
},
computed:{
info(){
return this.isHot?"炎热":"凉爽"
}
}
})
</script>
</body>
</html>
第三种用监视属性写
监视属性
监视属性watch:
- 当被监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视!!!
- 监视的两种写法:
(1)new Vue时传入watch属性
(2)通过vm.$watch()进行监视
监视属性第一种写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>天气案例-监视属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
今天天气很{{weather}} <br>
<button @click="toggleWeather">切换天气</button>
</div>
</body>
<script>
new Vue({
el:"#root",
data:{
isHot:true
},
computed:{
weather(){
return this.isHot?"炎热":"凉爽"
}
},
methods:{
toggleWeather(){
this.isHot=!this.isHot
}
},
watch:{
isHot:{
immediate:true, //初始化时候,调用handler一下
//handler什么时候调用?在isHot发生变化时候
handler(newValue,oldValue){
console.log("isHot被修改了,修改后的值为:"+newValue+",修改前的值为:"+oldValue);
}
},
//不仅data中的属性可以使用监视,计算属性也可以使用
weather:{
handler(newValue,oldValue){
console.log("weather被修改了,修改后的值为:"+newValue+",修改前的值为:"+oldValue);
}
}
}
})
</script>
</html>
监视属性第二种写法
当创建实例时候不知道要监测谁,后续根据用户行为是否监视再进行添加
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>天气案例-监视属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
今天天气很{{weather}} <br>
<button @click="toggleWeather">切换天气</button>
</div>
</body>
<script>
const vm=new Vue({
el:"#root",
data:{
isHot:true
},
computed:{
weather(){
return this.isHot?"炎热":"凉爽"
}
},
methods:{
toggleWeather(){
this.isHot=!this.isHot
}
}
})
vm.$watch("isHot",{
immediate:true,
handler(newValue,oldValue){
console.log("isHot修改了,修改后值为:"+newValue+",修改前值为"+oldValue);
}
})
</script>
</html>
深度监视
深度监视:
(1)Vue中的watch默认不监测对象内部值的改变(一层)
(2)配置deep:true可以监测对象内部值改变(多层)
备注:
(1)Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
(2)使用watch时根据数据的具体结构,决定是否采用深度监视
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>天气案例-深度监视</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
a的值是:{{numbers.a}} <br>
<button @click="numbers.a++">点我让a+1</button>
<hr>
b的值是:{{numbers.b}} <br>
<button @click="numbers.b++">点我让b+1</button>
</div>
</body>
<script>
new Vue({
el:"#root",
data:{
numbers:{
a:1,
b:1
}
},
watch:{
//监视多级结构中某个属性的变化
'numbers.a':{
handler(){
console.log("a被改变了");
}
},
//监视多级结构中所有属性的变化
numbers:{
deep:true,
handler(){
console.log("numbers改变了");
}
}
}
})
</script>
</html>
监视属性简写
监视属性第一种方式简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>天气案例-监视属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
今天天气很{{weather}} <br>
<button @click="isHot=!isHot">切换天气</button>
</div>
</body>
<script>
new Vue({
el:"#app",
data:{
isHot:true
},
computed:{
weather(){
return this.isHot?"炎热":"凉爽"
}
},
watch:{
//监视属性中没有immediate,deep等属性,只有handler时候可以简写
isHot(newValue,oldValue){
console.log("isHot被修改了,修改后:"+newValue+",修改前为:"+oldValue);
}
}
})
</script>
</html>
监视属性第二种方式简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>天气案例-监视属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
今天天气很{{weather}} <br>
<button @click="isHot=!isHot">切换天气</button>
</div>
</body>
<script>
const vm=new Vue({
el:"#app",
data:{
isHot:true
},
computed:{
weather(){
return this.isHot?"炎热":"凉爽"
}
},
})
vm.$watch("isHot",function(newValue,oldValue){
//监视属性中没有immediate,deep等属性,只有handler时候可以简写
console.log("isHot被修改了,修改后:"+newValue+",修改前为:"+oldValue);
})
</script>
</html>
watch与computed对比
姓名案例-使用监视属性写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>姓名案例-监视属性</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="lastName"> <br><br>
名:<input type="text" v-model="firstName"> <br><br>
全名:{{fullName}}
</div>
</body>
<script>
new Vue({
el:"#root",
data:{
lastName:"张",
firstName:"三",
fullName:"张-三"
},
watch:{
lastName(newValue){
this.fullName=newValue+"-"+this.firstName
},
firstName(newValue){
this.fullName=this.lastName+"-"+newValue
}
}
})
</script>
</html>
明显感觉计算属性写出来的方便些,但是若换成以下的例子,又会不一样了
姓名案例-1s之后再显示
监视属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>姓名案例-1s后显示</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
姓:<input type="text" v-model="lastName"> <br><br>
名:<input type="text" v-model="firstName"> <br><br>
全名:{{fullName}}
</div>
</body>
<script>
new Vue({
el:"#app",
data:{
lastName:"张",
firstName:"三",
fullName:"张-三"
},
watch:{
lastName(newValue){
setTimeout(()=>{
//函数为箭头函数,所以没有this,this只能往上层去找,上层是lastName,他的this是Vue,所以能执行成功。
//且必须写成箭头函数,否则this指代的是window
//因为定时器执行的回调是由js引擎执行的,所以写成普通函数就是this指代就是window
this.fullName=newValue+"-"+this.firstName
},1000)
},
firstName(newValue){
setTimeout(()=>{
this.fullName=this.lastName+"-"+newValue
},1000)
}
}
})
</script>
</html>
计算属性
computed:{
fullName(){
setTimeout(()=>{
console.log(this);
return this.lastName+"-"+this.firstName
},1000)
}
}
计算属性这样写的话是实现不了的,因为return给的是箭头函数,而不是给fullName,这样的话fullName就没有返回值了,因此,这样写就是错的了。
总结:computed和watch之间的区别
- computed能完成的功能,watch都能完成
- watch能完成的功能,computed不一定能完成。例如:watch可以进行异步操作
两个重要的小原则:
1.所有被Vue管理的函数,最好写成普通函数,这样this的指向才是 vm 或 组件实例对象
2.所有不被Vue管理的函数(定时器的回调函数,ajax的回调函数,Promise的回调函数等)最好写成箭头函数,这样this的指向才是vm或组件实例对象