计算属性和侦听器(消耗性能):watch:{ x ( ) { } }
-
1.侦听器属性必须和data中的数据源同名,因为侦听器是用于监听数据源属性是否发生变化,如果发生了变化,就执行侦听器属性里的代码 。
-
2.当侦听器监听的属性发生变化时,就会调用watch中对应的方法,
-
3.侦听器属性,比计算属性计算效率消耗大(因为是监听属性,一直在观察属性变化,所以消耗性能)
监听属性
解决修改了引用数据内部的属性值,页面会重新渲染,但是侦听器属性不会触发的方案
1.修改引用数据的引用:this.obj={age:"sjhd"}
2.深度监听:
obj:{
// 当我们点击了按钮2,发现控制台没有打印smg
// 是因为,侦听器只监听了obj这一层,发现引用数据并没有改变
// 所以,就不会执行里面的代码
// console.log("smg")
// 解决上面的问题:深度监听
deep:true
handler:()=>{
console.log("obj改变了")
}
}
关于计算属性和侦听器的完整代码:
<div class="app">
<p>{{n}}</p>
<button @click="change1">修改n</button>
<p>{{obj.age}}</p>
<button @click="change2">修改obj</button>
</div>
<script>
new Vue({
el:".app",
data:{
n:"hello",
obj:{
age:10
}
},
methods: {
change1(){
this.n="修改了"
},
change2(){
// this.obj.age="修改了引用数据内部的属性值:页面会重新渲染,但是侦听器属性不会触发"
// 解决修改了引用数据内部的属性值,页面会重新渲染,但是侦听器属性不会触发的问题
// 第一种方法:修改了引用数据的引用
// this.obj={age:"只有修改了引用数据的引用,才能触发侦听器属性"}
// 第二种方法:深度监听
this.obj.age="修改了引用数据内部的属性值,也想触发侦听器属性,必须深度侦听"
}
},
watch:{
// 侦听器属性:必须和data中的数据源同名
// 因为是侦听器,用于监听数据源属性是否发生变化
// 如果发生了变化,就执行函数n里面的代码
n(){
// 点击按钮后,发现打印了666
// 说明侦听器起作用了
console.log(666)
},
obj:{
// 当我们点击了按钮2,发现控制台没有打印smg
// 是因为,侦听器只监听了obj这一层,发现引用数据并没有改变
// 所以,就不会执行里面的代码
// console.log("smg")
// 解决上面的问题:深度监听
deep:true,
handler:()=>{
console.log("obj改变了")
}
}
}
})
</script>
相关案例:
案例1:汇率转换
<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">
//引入vue框架
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.js" type="application/javascript"></script>
<title>Document</title>
</head>
<body>
<!-- 汇率转换 -->
<div class="app">
<!-- v-model:双向数据绑定 -->
RMB:<input type="text" v-model="rmb">
doller:<input type="text" v-model="doller">
</div>
<script>
new Vue({
el:".app",
data:{
rmb:0,
doller:0
},
methods: {
},
watch:{
// rmb(){
// // console.log(arguments)
// // 改变输入框,发现实参打印有两个值
// // 一个值是改变前的,一个是改变后的
// //所以直接设置两个形参变量
// }
rmb(newvalue,oldvalue){
// 进行汇率转换,取两位小数,且小数后不为00
this.doller=(newvalue/6.9).toFixed(2)*100/100
},
doller(newvalue,oldvalue){
this.rmb=newvalue*6.9
}
}
})
</script>
</body>
案例2:提醒用户余额不足
<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">
<!-- 引入vue框架 -->
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.js" type="application/javascript"></script>
<title>Document</title>
</head>
<body>
<div class="app">
<p>{{money}}</p>
<button @click="fn">消费</button>
</div>
<script>
var vm=new Vue({
el:".app",
data() {
return {
money:100
}
},
methods:{
fn(){
// 每点击一次,就消费10
this.money-=10
}
},
watch:{
money(newvalue,oldvalue){
// 当监听器监听到newvalue小于30时,就提醒用户余额不足了
if(newvalue<30){
alert("发短信给用户,余额不足,只有30元了")
}
}
}
})
</script>
案例3:监听播放进度条,音乐试听
<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">
<!-- 引入vue框架 -->
<script src="https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.js" type="application/javascript"></script>
<title>Document</title>
</head>
<body>
<style>
.slider{
width: 400px;
height: 20px;
background-color: aquamarine;
position: relative;
left: 100px;
top: 100px;
border-radius: 10px;
}
.sliderbar{
width: 30px;
height: 30px;
border-radius: 50%;
background-color: cadetblue;
position: absolute;
left: 0px;
top: -5px;
}
</style>
<div class="app">
进度条:
<div class="slider">
<div class="sliderbar" :style="{left:x}"></div>
</div>
<button @click="start">start</button>
</div>
<script>
new Vue({
el:".app",
data:{
currenttime:0,
total:240,
x:0
},
methods:{
start(){
// 点击了按钮,就通过定时器进行改变currenttime的值
this.timer=setInterval(()=>{
this.currenttime+=0.1
},100)
}
},
watch:{
//监听curretime
currenttime(value){
// value:代表改变后的值
// x:代表进度条的进度
this.x=370*value/240+"px"
// 超过60s,就结束试听
if(value>=60){
// 清除定时器
clearInterval(this.timer)
alert("试听结束")
}
}
}
})
</script>