Vue——计算属性和侦听器、及相关案例

232 阅读1分钟

计算属性和侦听器(消耗性能):watch:{ x ( ) { } }

  • 1.侦听器属性必须和data中的数据源同名,因为侦听器是用于监听数据源属性是否发生变化,如果发生了变化,就执行侦听器属性里的代码 。

  • 2.当侦听器监听的属性发生变化时,就会调用watch中对应的方法,

  • 3.侦听器属性,比计算属性计算效率消耗大(因为是监听属性,一直在观察属性变化,所以消耗性能)

监听属性

image.png

解决修改了引用数据内部的属性值,页面会重新渲染,但是侦听器属性不会触发的方案

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>