watch监听属性

在Vue中,也存在着这个重要的监听属性,同样也是监听Vue实例中数据的变化。先上代码
<!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 type="text/javascript" src="http://ljy0427.online/js/vue.js"></script>
    <style>
        div {
            margin-top: 10px;
        }
    </style>
</head>

<body>
    <div id="app">
        <h2>苹果</h2>
        <div>数量:<input v-model="num"></div>
        <div>价格:<input v-model="price.toFixed(2)"></div>
        <div>总价:{{totalPrices}}</div>
        <div>我有:<input v-model="OwnPrice" @keyup.enter="buy"></div>
        <div>可以买:{{buyNum}}个</div>
    </div>
</body>

<script type="text/javascript">
    Vue.config.productionTip = false
    var vm = new Vue({
        el: '#app',
        data: {
            num: 2,
            price: 2.00,
            OwnPrice: 0,
            buyNum: 0,
            totalPrices:0
        },
        watch:{
            num:{
                handler(newValue,oldValue){
                    console.log([newValue,oldValue]);
                }
            }
        },
        methods: {
            buy() {
                this.totalPrices = this.OwnPrice
                console.log("购买");
            }
        }
    });
</script>

</html>
通过以上代码,可以发现,watch和computed有点类似,但要记住一点,computed能够完成的事情,watch也能完成,并且,computed不能完成的某些需求,watch也能完成。

首先看watch怎样写

1.具体代码

watch:{
    num:{
        handler(newValue,oldValue){
            console.log([newValue,oldValue]);
        }
    }
}
首先可以看出最大的区别,就是watch的监听属性,必须要先在data中声明,而且还有个最大的特点,就是watch同时还可以监听computed中的计算属性。

并且最大的区别就是,这里通过这种对象的方式定义监听属性的时候,使用的handler函数,并不是想computed那样是通过set,get方式,这里就可以看出,其两者的底层实现原理不同了。

并且这和hadnler函数,会接收两个参数值,第一个参数就是当前监听属性改变值的新值,第二个参数就是当前监听这个属性在发生改变之前的值。

同时还可以联想到,既然是通过这种方式定义的监听属性,那么就应该还存在着其他的配置属性,确实存在的,只不过这里只简单介绍两个配置属性immediate和deep

immediate

immediate译为立即,在wathc中的作用也是这样,就是让当前监听属性的时间立即执行,其默认值为false。
num:{
    immediate:true,
    handler(newValue,oldValue){
        console.log([newValue,oldValue]);
    }
}

这里就可以看出来将该属性设置为true之后,当Vue实例渲染完成之后,就会立即执行该handlr函数,并且会发现,oldValue为undefined,这里我的理解是,在Vue实例构建的时候,只是构建了这个num变量,就相当于var num;这种时候num的值就为undefined了,然后渲染结束之后,再为其赋值,所以newValue是就是自己在data中所定义的值了。

deep

deep译为深度,在watch中的作用是深度监听
<body>
    <div id="app">
        <div>
            水果名称:{{fruit.name}}
        </div>
        <div>
            水果价格:{{fruit.price}}
        </div>
        <div><input type="text" v-model="changeName" placeholder="输入修改名称"> <button @click="CN">点击修改水果名称</button></div>
        <div><input type="text" v-model="changePirce" placeholder="输入修改价格"> <button @click="CP">点击修改水果价格</button></div>
    </div>
</body>
<script type="text/javascript">
    Vue.config.productionTip = false
    var vm = new Vue({
        el: '#app',
        data: {
            fruit: {
                name: "苹果",
                price: "2.00"
            },
            changePirce: "",
            changeName: ""
        },
        watch: {
            fruit: {
                immediate: true,
                handler(newValue, oldValue) {
                    console.log([newValue, oldValue]);
                }
            }
        },
        methods: {
            CN() {
                console.log(`名称发生了改变,值=${this.changeName}`);
                this.fruit.name=this.changeName
            },
            CP() {
                console.log(`价格发生了改变,值=${this.changePirce}`);
                this.fruit.changePirce=this.changePirce
            },
        }
    });
</script>

</html>
在上述代码中,改变了一下例子,将水果当成了一个对象,定义在了data中,这种时侯,看下效果

从这里就可以看出了,当水果名称改变时,watch监听属性不起作用了,其实这个就是由于没有开启watch的深度监听所导致的。

watch这样修改试试
watch: {
    fruit: {
        immediate: true,
        handler(newValue, oldValue) {
            console.log([newValue, oldValue]);
        }
    },
    "fruit.name":{
        handler(newValue, oldValue) {
            console.log([newValue, oldValue]);
        }
    },
    "fruit.price":{
        handler(newValue, oldValue) {
            console.log([newValue, oldValue]);
        }
    }
}

发现这种方式确实改变了,但是这种方式,有个弊端,很明显,也就是如果这个对象中有很多属性,那岂不是要写很多这种方法,代码的冗余程度就增加了,这种时候就需要deep这个配置对象了,其默认值为false,将其修改成true即可
fruit: {
    immediate: true,
    deep:true,
    handler(newValue, oldValue) {
        console.log([newValue, oldValue]);
    }
}

效果如图,这种时候,当属性的值发生改变是,handler也触发了,但是如果按照之前说的handler所接收得到两个参数,第一个是新值,第二个是修改之前的值,但是这里却输出的都一样啊,这个我认为就验证了我的观点了,这里传入的是一个地址,没有对地址修改,所以以前的值都一样,修改的只是其中的某一个属性

watch简写

watch也有简写形式,当不考虑这些配置对象的时候,即immediate和deep等时,就可以采用简写形式
 fruit(newValue, oldValue){
      console.log([newValue, oldValue]);
      }
最后修改:2022 年 01 月 10 日