文章目录
监视属性
引例
实现效果:点击切换天气按钮,天气可以在炎热和凉爽之间切换。
普通实现
实现:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
<script type='text/javascript'>
Vue.config.productionTip = false;
new Vue({
el:'#root',
data: {
isHot:true
},
computed:{
info(){
return this.isHot?"炎热":"凉爽"
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
})
</script>
</body>
</html>
也可以不使用函数,直接在 @click
中对变量进行处理
即绑定事件的时候:@xxx="yyy"
yyy可以写一些简单的语句,但是如果语句比较复杂就不适合这样写了
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="isHot = !isHot">切换天气</button>
</div>
<script type='text/javascript'>
Vue.config.productionTip = false;
new Vue({
el:'#root',
data: {
isHot:true
},
computed:{
info(){
return this.isHot?"炎热":"凉爽"
}
},
// methods: {
// changeWeather(){
// this.isHot = !this.isHot
// }
// },
})
</script>
</body>
</html>
使用监视属性watch检测天气变化
监视的特点:
- 当被监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视
- 有两种监视方法
第一种配置方法,设置watch属性
使用watch监视需要设置配置属性watch
格式如下:
watch:{
要监视的属性(可以是vue的普通属性也可以是计算属性):{
immediate:true,//初始化时执行一次handler
// 要监视的属性的值发生了改变就执行handler函数
//newValue代表修改后的值,oldValue代表修改前的值
handler(newValue,oldValue){
console.log("修改了",newValue,oldValue)
}
}
}
代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
<script type='text/javascript'>
Vue.config.productionTip = false;
new Vue({
el:'#root',
data: {
isHot:true
},
computed:{
info(){
return this.isHot?"炎热":"凉爽"
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true,//初始化时执行一次handler
// isHot的值发生了改变就执行handler函数
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
},
info:{
immediate:true,//初始化时执行一次handler
// isHot的值发生了改变就执行handler函数
handler(newValue,oldValue){
console.log("info被修改了",newValue,oldValue)
}
},
}
})
</script>
</body>
</html>
输出:
使用vm对象进行监视
格式
vm.$watch('要监视的属性',{
immediate:true,//初始化时执行一次handler
// 要监视的属性t的值发生了改变就执行handler函数
handler(newValue,oldValue){
console.log("监视的属性修改了",newValue,oldValue)
}
})
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data: {
isHot: true,
},
computed: {
info() {
return this.isHot ? "炎热" : "凉爽";
},
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
},
},
});
vm.$watch("isHot", {
immediate: true, //初始化时执行一次handler
// isHot的值发生了改变就执行handler函数
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
},
});
vm.$watch("info", {
immediate: true, //初始化时执行一次handler
// isHot的值发生了改变就执行handler函数
handler(newValue, oldValue) {
console.log("info被修改了", newValue, oldValue);
},
});
</script>
</body>
</html>
两种监视的使用情况
- watch监视适用于已经确定好检测对象的情况
- vm.$watch监视适用于检测对象不确定的情况
深度监视
监视多级结构中某个属性的变化(引例,不是深度监视)
即如果一个属性对象,我们想要监视对象中某一个属性的变化,这时候就用到深度监视。
因为需要使用.
获取对象属性,所以这里监视的对象需要用引号
引起来。
格式:
watch:{
'numbers.a':{
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
}
}
实际上配置对象的属性名本来就是要加引号的,不加引号只是简写形式,如果出现了.属性这类情况引号就不可以省略了。
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3>a的值是{{number.a}}</h3>
<button @click="number.a++">点我a加1</button>
</div>
<script type='text/javascript'>
Vue.config.productionTip = false;
const mv = new Vue({
el:'#root',
data: {
number:{
a:1,
b:1
}
},
watch:{
'number.a':{
handler(newValue,oldValue){
console.log("a被修改了",newValue,oldValue)
}
}
}
})
</script>
</body>
</html>
监视多级结构中所有属性的变化(——是深度监视)
当我们想要监视number中所有属性的变化,即number中任何一个属性发生了改变就进行监视输出。
- 直接监视number
'number':{
handler(newValue,oldValue){
console.log("number被修改了",newValue,oldValue)
}
}
不可行,因为number监视的是number的值,而number的值是它所指向的对象的地址,所以他监视的不是属性值a和b的变化。
- 这时候就需要用到深度检测了
是需要设置deep:true,
就可以使number监视的是number的对象的值,即属性值a和b的变化。
'number':{
deep:true,
handler(newValue,oldValue){
console.log("number被修改了",newValue,oldValue)
}
}
eg:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h3>a的值是{{number.a}}</h3>
<button @click="number.a++">点我a加1</button>
</div>
<script type='text/javascript'>
Vue.config.productionTip = false;
const mv = new Vue({
el:'#root',
data: {
number:{
a:1,
b:1
}
},
watch:{
'number.a':{
handler(newValue,oldValue){
console.log("a被修改了",newValue,oldValue)
}
},
'number':{
deep:true,
handler(newValue,oldValue){
console.log("number被修改了",newValue,oldValue)
}
}
}
})
</script>
</body>
</html>
深度监视小结
深度监视:
(1)Vue中的watch默认不监测对象内部值的改变(一层)。
(2)配置deep:true可以监测对象内部值改变(多层)。
注意:
(1)vue自身可以监测对像内部值的改变,但Vue提供的watch默认不可以!
(2)使用watch时根据数据的具体结构,决定是否采用深度监视。
监视的简写
当监视的对象只有 handler配置
时就可以开启简写模式
watch属性监视的简写
watch:{
isHot:{
handler(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
}
},
}
可以简写为
watch:{
isHot(newValue,oldValue){
console.log("isHot被修改了",newValue,oldValue)
},
}
vm对象监视的简写
vm.$watch("isHot", {
handler(newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
},
});
可简写为
vm.$watch("isHot", function(newValue, oldValue){
console.log("isHot被修改了", newValue, oldValue);
})
计算属性和监视属性的对比
代码量对比
实现效果:
计算属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstname"><br/>
名:<input type="text" v-model="lastname"><br/>
姓名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el:'#root',
// 在vue中会将data中的值看作属性
data: {
firstname:'张',
lastname:'三'
},
// 计算属性
// 计算属性:将写完的属性进行加工计算生成一个全新的属性
computed:{
fullName:{
// get作用:有人读取fullname时会调用get,且返回值作为fullname的值
get(){
// 此处的this是vm
return this.firstname +"-"+this.lastname
},
}
}
})
</script>
</body>
</html>
监视属性实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>姓名案例</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstname" /><br />
名:<input type="text" v-model="lastname" /><br />
姓名:<span>{{fullName}}</span>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
// 在vue中会将data中的值看作属性
data: {
firstname: "张",
lastname: "三",
fullName: "张-三",
},
watch: {
// 简写
firstname(newValue, oldValue) {
this.fullName = newValue + "-" + this.lastname;
},
lastname(newValue, oldValue) {
this.fullName = newValue + "-" + this.lastname;
},
},
});
</script>
</body>
</html>
在这个案例中,计算属性更方便简单一些。
异步回调对比
需求,当姓改变的时候,一秒后名字再改变:
- 计算属性无法实现异步操作
computed:{
fullName:{
get(){
setTimeout(() => {
// 调用箭头函数之后,返回值就是箭头函数的返回值了,而fullName就没有返回值了,所以会出错
return this.firstname +"-"+this.lastname
}, 1000);
},
}
}
输出结果:
- watch可以实现异步操作
watch: {
// 简写
firstname(newValue, oldValue) {
setTimeout(() => {
this.fullName = newValue + "-" + this.lastname;
}, 1000);
},
lastname(newValue, oldValue) {
this.fullName = newValue + "-" + this.lastname;
},
},
问题 : 如果setTimeout中写的不是箭头函数,而是普通函数那么this是谁?
- 答案是Windows,因为是windows为setTimeout设置的函数,
问题 :为什么setTimeout中写的是箭头函数,而this是vm? - 因为箭头函数没有this他就会向外找this,外层的this是vm
对比小结
computed和Iwatch之间的区别:
1.computed能完成的功能,watch都可以完成。
2.watch能完成的功能,computed不一定能完成,例如: watch可以进行异步操作。
两个重要的原则:
- 所
被Vue管理的函数
,最好写成普通函数
,这样this的指向才是vm或组件实例对象
。 - 所有
不被Vue所管理的函数
(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数
,这样this的指向才是vm或组件实例对象。
目的都是使this指向vue。