Vue中,Watch与Computed的用法与场景分析

392 阅读3分钟

Watch(侦听器)

作用:监听某一个属性发生变化时候需要执行的操作。

场景:当一条数据改变,影响多条数据的时候。(计算属性:当多条数据改变影响一条数据的时候。如:购物车 商品总价格)。

示例:

1.监听属性,用属性名作为函数名,接收两个参数分别是:新值(改变后的值) 旧值(改变前的值)。

    data() {
            return {
                count: 0,
                person: {
                    name: '张三',
                    age: 18,
                    son: {
                        name: '张四',
                        age: 1
                    }
                }
            }
        },
        watch:{
            count(newVal, oldVal) {
                console.log(`触发watch监听-----新值是${newVal},旧值是${oldVal}`);
            },
        }
    

2.监听对象属性,对象属性名要加单引号'person.son.name',接收两个参数分别是:新值(改变后的值) 旧值(改变前的值)。

    data() {
            return {
                count: 0,
                person: {
                    name: '张三',
                    age: 18,
                    son: {
                        name: '张四',
                        age: 1
                    }
                }
            }
        },
        watch:{ 
            'person.son.name'(newVal, oldVal) {
                console.log(`触发watch监听-----新值是${newVal},旧值是${oldVal}`);
            },
        }
    

3.监听对象里面所有属性。

需要设置deep为true表示深度监听对象里面的所有属性。

immediate(立即的) watch监听数据发生改变的时候才会触发,设置此属性为true,在组件创建的时候就会触发,也就是数据初次加载就会触发。

    data() {
            return {
                count: 0,
                person: {
                    name: '张三',
                    age: 18,
                    son: {
                        name: '张四',
                        age: 1
                    }
                }
            }
        },
     watch:{
         person: {
                handler(newVal,oldVal){
                    console.log(newVal);  //打印的是person对象改变后的值 此时person.son.name是王五
                    console.log(oldVal);
                },
                deep:true, //深度监听默认是false  递归监听对象里面的属性
                immediate: true  //在组件创建的时候立即执行
            }
     }
     

完整示例

        el: '#app',
        data() {
            return {
                count: 0,
                person: {
                    name: '张三',
                    age: 18,
                    son: {
                        name: '张四',
                        age: 1
                    }
                }
            }
        },
        mounted() {
            //1秒后改变son里面的name属性
            setTimeout(() => {
                this.person.son.name = '张五'
            }, 1000);
            //每隔1秒让count加一
            setInterval(() => {
                this.count++
            }, 1000);
        },
        watch: {
            //监听属性
            count(newVal, oldVal) {
                console.log(`触发watch监听-----新值是${newVal},旧值是${oldVal}`);
                //触发watch监听----- 新值是1, 旧值是0
                //触发watch监听----- 新值是2, 旧值是1
                //触发watch监听----- 新值是3, 旧值是2
                //触发watch监听----- 新值是4, 旧值是3
            },
            
             //监听对象属性
            'person.son.name'(newVal, oldVal) {
                console.log(`触发watch监听-----新值是${newVal},旧值是${oldVal}`);
                //触发watch监听-----新值是张五,旧值是张四
            },
            
            //监听整个对象的所有属性(一般不建议使用)
            person: {
                handler(newVal,oldVal){
                    console.log(newVal);  //打印的是person对象改变后的值 此时person.son.name是王五
                    console.log(oldVal);
                },
                deep:true, //深度监听默认是false  递归监听对象里面的属性
                immediate: true  //在组件创建的时候立即执行
            }
        }
    })

对比Watch和Computed的使用场景

watch 用于一个数据改变影响多条数据。

computed用于多条数据影响一条数据。

计算属性(computed)是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
这就意味着只要值还没有发生改变,多次访问计算属性会立即返回之前的计算结果,而不必再次执行计算属性。
而methods只要调用就会触发。

比如购物车计算总价格,如果使用watch则需要监听每个属性的改变,代码冗余较多。

示例

const app = new Vue({
        el: '#app',
        data() {
            return {
                applePrice: 20, //单价
                appleCount: 1,  //数量
                bananaPrice: 30,
                bananaCount: 1,
                allPrice:0
            }
        },
        mounted() {
            //1秒后改变修改数量
            setTimeout(() => {
                this.bananaCount = 2;
                this.appleCount = 3;
            }, 1000);

        },
        computed: {
            resultPrice(){
                let result =  this.applePrice * this.appleCount + this.bananaPrice * this.bananaCount;
                return result;
            }
        },
        watch: {
            //需要对所有属性进行监听不合理。
            appleCount() {
                this.allPrice = this.applePrice * this.appleCount + this.bananaPrice * this.bananaCount;
            },

            bananaCount() {
                this.allPrice = this.applePrice * this.appleCount + this.bananaPrice * this.bananaCount;
            },
        }
    })