简单聊聊 computed 和 watch 的区别?

computed:计算属性
  • 调用属性时不需要加括号 (最后面解释了为什么不加括号!!
  • 根据依赖会自动缓存,如果依赖不变就不会重新计算
  • 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
  • 如果一个属性是由其他属性计算出来的,这个属性依赖其他属性,是多对一或一对一,一般用computed
  • 如果computed的属性值是函数,那么默认会走get方法,函数的返回值就是属性的属性值,在computed,属性都有get,set方法,当数据变化,就会调用set方法。
new Vue({
    data: {
        user: {
            email: "123456@qq.com",
            nickname: "黄埔",
            phone: "123456789"
        }
    },
    computed: {
        displayName: {
            get() {
                const user = this.user;
                return user.nickname || user.email || user.phone;
            },
            set(value) {
                console.log(value);
                this.user.nickname = value;
            }
        }
    },
 
    template: `
    <div>
      {{displayName}}
      <div>
      {{displayName}}
      <button @click="add">set</button>
      </div>
    </div>
  `,
    methods: {
        add() {
            console.log("add");
            this.displayName = "军校"; //调用时直接写属性
        }
    }
}).$mount("#app");

 

 
watch:监听
 
  • 不支持缓存,数据变化,直接会触发相应的操作
  • watch支持异步
  • 监听的函数接收里两个参数,第一个参数是最新的值,第二个参数是输入之前的值
  • 当一个属性变化时,需要执行对应的操作:一对多
  • 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,可以选择是否触发其他操作,有两个参数:     
                 immedit:组件加载立即触发回调函数执行(决定函数是否初始化就执行,执行为true,相反为false)
                 deep:深度监听(看监听对象里面的属性是否变化)为了发现对象内部值的变化,复杂类型的数据时使用,
                            例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。
                            deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
 
 
new Vue({
    data: {
        n: 0,
        history: [],
        inUndoMode: false
    },
    watch: {
        n: function (newValue, oldValue) {
            console.log(this.inUndoMode);
            if (!this.inUndoMode) {
                this.history.push({ from: oldValue, to: newValue });
            }
        }
    },
    // 不如用 computed 来计算 displayName
    template: `
    <div>
      {{n}}
      <hr />
      <button @click="add1">+1</button>
      <button @click="add2">+2</button>
      <button @click="minus1">-1</button>
      <button @click="minus2">-2</button>
      <hr/>
      <button @click="undo">撤销</button>
      <hr/>
 
      {{history}}
    </div>
  `,
    methods: {
        add1() {
            this.n += 1;
        },
        add2() {
            this.n += 2;
        },
        minus1() {
            this.n -= 1;
        },
        minus2() {
            this.n -= 2;
        },
        undo() {
            const last = this.history.pop();
            console.log(last);
            this.inUndoMode = true;
            console.log("ha" + this.inUndoMode);
            const old = last.from;
            this.n = old;
            // watch n 的函数会异步调用,当这里得到上个个数字的老n值会重新赋值给n,watch会重新计算n值,会重新push数组
            this.$nextTick(() => { 
                this.inUndoMode = false;  //这里也设置为异步,和n同级别,就会和n的赋值依次执行
            });
        }
    }
}).$mount("#app");

 

 immedit:组件加载立即触发回调函数执行
 
new Vue({
    data: {
        user: {
            email: "123456789@qq.com",
            nickname: "玲珑",
            phone: "123456789"
        },
        displayName: ""
    },
    watch: {
        "user.email": {
            handler: "changed",
            immediate: true // 第一次渲染触发 watch
        },
        "user.nickname": {
            handler: "changed",
            immediate: true // 第一次渲染触发 watch
        },
        "user.phone": {
            handler: "changed",
            immediate: true // 第一次渲染触发 watch
        }
    },
 
 
    template: `
    <div>
       {{displayName}}
       <button @click="user.nickname=undefined">remove nickname</button>
    </div>
  `,
    methods: {
        changed() {
            console.log(arguments);
            const user = this.user;
            this.displayName = user.nickname || user.email || user.phone;
        }
    }
}).$mount("#app");

 

 
deep:深度监听
 
new Vue({
    data: {
        n: 0,
        obj: {
            a: "a"
        }
    },
    template: `
    <div>
      <button @click="n += 1">n+1</button>
      <button @click="obj.a += 'hi'">obj.a + 'hi'</button>
      <button @click="obj = {a:'a'}">obj = 新对象</button>
    </div>
  `,
    watch: {
        n() {
            console.log("n 变了");
        },
        obj:{
            handler(){
                console.log("obj 变了");
            },
            deep:true   //监听obj里的数值变化,obj也变化了
        },
        "obj.a": function() {
            console.log("obj.a 变了");
        }
    }
}).$mount("#app");

 

总结:
  • 具体需要返回值到页面上的一般用计算属性 computed
  • 监听数据变化而不需要返回值的时候用侦听属性 watch
 
 

 
computed和methods区别
 
一、computed与methods的区别:
 
  • 实质上computed计算属性中定义的是属性而不是函数,所以使用时直接用{{xxx}},而不要使用{{xxx()}};
  •  而methods中定义的是函数,因此使用时需要{{xxx()}}。
  • 计算属性computed被使用时会进行缓存,如果需要多次使用,则只需要调用1次;
  •  而methods中的函数无缓存,如果需要使用n次,则需要调用n次。
  • 因此,需要多次使用时,推荐使用计算属性computed。
 
二、为什么使用计算属性computed时不用()
 
计算属性的实质为属性,其中定义了set()方法和get()方法:
computed: {
        displayName: {
            get() {
                const user = this.user;
                return user.nickname || user.email || user.phone;
            },
            set(value) {
                console.log(value);
                this.user.nickname = value;
            }
        }
    }

 

 
而一般使用中不需要set方法,我们只需要get方法,因此计算属性一般为“只读属性”。
去掉无用的set方法后,computed属性简写为我们常见的方式:
computed: {
        displayName: funcation(){
                const user = this.user;
                return user.nickname || user.email || user.phone;
        }
    }
 
因此,只是形式上看起来像函数,实质上computed计算属性是属性。使用计算属性时,直接使用{{fullName}},不要加()。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2021-02-27 22:37  蛰鸣  阅读(208)  评论(0编辑  收藏  举报