目录
1.天气案例引入
2.计算属性实现案例回顾
2.1 需要注意的坑
2.2 实现小技巧
3.监视属性
3.1 watch配置的监视
3.2 计算属性是否可监视?
3.3 除watch配置之外的另一种监视办法
3.4 两种监视方式的用法
4.总结
1.天气案例引入
今天我们来讲一下Vue的监视属性。还是通过一个小案例来引入。
我们需要实现的案例功能是在页面上输出今天天气很凉爽/炎热,而天气的状态可以通过按钮来切换。而且在切换的同时在控制台输出:天气变化了,现在是:凉爽,原来是:炎热。可以看到之前和之后的状态。
我们先来简单实现一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{isHot ? '炎热' : '凉爽'}}</h2>
<button>切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
new Vue({
el:'#root',
data:{
isHot:true
}
})
</script>
</html>
实现效果:
我们可以看到简单的界面效果出来了。那可不可以实现切换呢?我们可以用Vue的开发者工具试验一下。
说明切换是可以起作用的。
2.计算属性实现案例回顾
但是我们可以看到 {{isHot ? '炎热' : '凉爽'}} 这样的表达式又写的过于麻烦了,既然我们上一节学了计算属性,那我们这里就用计算属性来实现一下。顺便给按钮也绑定切换事件。
由于天气是否炎热或者凉爽,我们只需要计算出来给别人看就行,所以我们这里在写的时候就可以用计算属性的简写形式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click = "changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
}
})
</script>
</html>
实现效果:
到这里我们这个小案例就讲完了,但是这个小案例特别适合讲两个东西,一个是坑,一个是技巧。
2.1 需要注意的坑
先说坑,Vue的开发者工具有个缺点,如果用到的元素在页面上不存在,即使元素值改变了,在工具中也不会体现,因为Vue的开发者工具认为,既然你都没用到这个值,就算你变化了,我也没必要给你展示变化。
我们下面可以试试将模板中的info去掉,然后再点击切换,看看是不是这么回事。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很</h2>
<button @click = "changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
}
})
</script>
</html>
实现效果:
我们可以看到实际上数据已经改了,但是因为元素并没有在页面上用到,所以Vue的开发者工具中并没有实时更新。
2.2 实现小技巧
在刚才的按钮切换实现方法中我们可以看到,我们为了实现点击切换,写了@Click,写了methods,又写了changeWeather方法,最终其实只是为了实现一句话this.isHot = !this.isHot,那么如果是像这样的情况,我们可以把方法写的更加简单一点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click = "isHot = !isHot">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
}
})
</script>
</html>
实现效果:
我们可以看到直接把方法中的内容写到@click后面也可以实现同样的效果。理论上来说,即使有很多行语句也可以通过分号分隔的方式这样去写。比如下面这样。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}},{{x}}</h2>
<button @click = "isHot = !isHot;x++">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true,
x:1
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
}
})
</script>
</html>
实现效果:
但是有一种情况是例外的,比如alert语句是不能用这种写法的,我们直接用就会报错。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}},{{x}}</h2>
<button @click = "alert(1)">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true,
x:1
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
}
})
</script>
</html>
这是因为alert并不存在于vm身上,而是在外部的window身上。如果我们想这样用的话,可以先把window挂到vm身上,然后再通过window调用alert即可。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}},{{x}}</h2>
<button @click = "window.alert(1)">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true,
x:1,
window
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
}
})
</script>
</html>
3.监视属性
接下来我们就把刚才的天气案例,用监视属性去写一下。
监视属性,顾名思义,其实就是监视某一个属性的变化。
刚刚我们之所以能够实现天气的切换,是因为我们不断的在修改isHot的值,接下来我们就监测一下isHot的改变。只要isHot变了,我们就要收到通知。
3.1 watch配置的监视
在Vue中,如果想要实现监视,我们就要用到一个全新的配置项watch。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click = "changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
//handler什么时候调用?当isHot发生改变时
handler(){
console.log('isHot被修改了')
}
}
}
})
</script>
</html>
我们可以看到当isHot属性被修改的时候是可以即使收到通知的。其实watch不仅能告诉我们它的值被修改了,其实还可以通过参数的方式告诉我们修改前和修改后的值是多少。
在watch中不仅有handler属性,还有 immediate属性,默认为false,如果为true的话,则会在初始化的时候让handler调用一下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click = "changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = 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(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
}
})
</script>
</html>
从上面我们可以看到在页面初始化的时候handler就被马上调用了一下。其实配置监视还有另外一种办法,不仅仅是使用watch了。那么在讲这个别的办法之前,我们再说一个细节上的点,为以后的路扫清一些障碍。
3.2 计算属性是否可监视?
刚刚我们监视的是isHot,而isHot是谁?是我们亲手在data中配置的属性。那么这里就会引申出一个问题,我们在computed中计算出来的属性也是属性,那么它能不能监视到计算属性呢?我们可以验证一下,去监视info这个计算属性,看能不能监视到。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click = "changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
info:{
immediate:true,
//handler什么时候调用?当isHot发生改变时
handler(newValue,oldValue){
console.log('info被修改了',newValue,oldValue)
}
}
}
})
</script>
</html>
可以看到计算属性同样也可以监视到的。
3.3 除watch配置之外的另一种监视办法
下面我们再说一下另外一种除watch之外的监视的办法。
就是不通过watch配置,而是通过vm来实现监视。
首先我们需要保证实例已经创建完了,创建完之后,我们可以通过vm.$watch(),也能实现监视,它需要传递两个参数。第一个参数要告诉它需要监视谁,第二个参数就需要传递一个配置项来告诉他怎么监视。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click = "changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止Vue在启动时生成生产提示
const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
// watch:{
// info:{
// immediate:true,
// //handler什么时候调用?当isHot发生改变时
// handler(newValue,oldValue){
// console.log('info被修改了',newValue,oldValue)
// }
// }
// }
})
vm.$watch('isHot',{
immediate:true,
//handler什么时候调用?当isHot发生改变时
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
</script>
</html>
实现效果:
3.4 两种监视方式的用法
上面说的两种监视方式,在实际工作中的用法是这样的。
如果我们一开始就知道需要去监视谁,那么就可以使用watch提前配置好。
如果我们一开始不知道需要监视谁,而是需要根据后续用户的一些行为来决定到底监视谁,这个时候就可以使用vm.$watch去实现动态监视。
4.总结
1.当监视属性变化时,回调函数handler自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视!
3.监视的两种写法:
(1)new Vue的时候传入watch配置
(2)通过vm.$watch监视