Advanced-Frontend / Daily-Interview-Question

我是依扬(木易杨),公众号「高级前端进阶」作者,每天搞定一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己。

Home Page:https://muyiy.cn/question/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

第 146 题:Vue 中的 computed 和 watch 的区别在哪里

yygmind opened this issue · comments

第 146 题:Vue 中的 computed 和 watch 的区别在哪里
commented

watch监听一个实例上的变量的变化,可以接受2个参数(newValue, oldValue),即变化的最新值和上一次变化的旧值
computed是计算属性,即示例上的数据不改变会有缓存,当下一次遇到的属性如果之前使用过,就会把缓存中的值放上去

computed:计算属性

计算属性是由data中的已知值,得到的一个新值。
这个新值只会根据已知值的变化而变化,其他不相关的数据的变化不会影响该新值。
计算属性不在data中,计算属性新值的相关已知值在data中。
别人变化影响我自己。
watch:监听数据的变化

监听data中数据的变化
监听的数据就是data中的已知值
我的变化影响别人

1.watch擅长处理的场景:一个数据影响多个数据

2.computed擅长处理的场景:一个数据受多个数据影响

说一下个人见解,
1、watch就是单纯的是监听某个数据的变化,支持深度监听
2、computed是计算属性,是依赖于某个或者某些属性值,只有当依赖的数据发生变化时,才会发生变化;
commented

计算属性,实质就是将变量的get属性重写成了你所定义的那个函数,也就是说实现了数据劫持那一步,无所谓data还是props,都可以作为计算属性函数的依赖值。

属性监听,其实也就是观察者模式将变量丢进了观察者收集器当中,变化可以被通知到。

计算属性是定义变量的get和set,对于复杂数据类型,引用地址不变,则不会触发set,get会缓存,不会重复计算。watch是变量变化时做点什么(触发一些函数),数组的一些变异的方法(push/splice/shift等)不会触发set,只能触发watch。

commented

computed:计算,顾名思义就是根据相关数据的变化得到一个新值。
watch:看,发现观察的东西有变更了,进行一系列的操作。
计算属性相当于一个变量,由一个方法构成,里面涉及到的data数据,就是相关数据。通常只做“计算结果”的逻辑,不改变数据。
watch则是需要根据观察的“对象”,在其变动时执行相关逻辑。

commented

watch 会生成一个watcher对象,在监视的属性每次变动时都会触发回调
computed 则是生成一个惰性的watcher,只有在取值操作(getter触发)时收集依赖且计算值
当有依赖变动时仅将 dirty 置为 true,不做计算操作
当有取值操作时,根据自身标记 dirty 属性返回上一次计算结果/重新计算值

Watch
    watch用于观察和监听页面上的vue实例,当你需要在数据变化响应时,执行异步操作,或高性能消耗的操作,那么watch为最佳选择

computed
    可以关联多个实时计算的对象,当这些对象中的其中一个改变时都会触发这个属性
    具有缓存能力,所以只有当数据再次改变时才会重新渲染,否则就会直接拿取缓存中的数据。

commented

vue:2.6.10

<template>
    <div class="container" id="home">
        <p>{{a}}</p>
        <p>{{b}} </p>
        <p>{{d}}</p>
        <button @click="change">改变a</button>
    </div>
</template>
<script>

    export default {
        data() {
            return {
                a: 1,
                b: 2
            }
        },
        methods: {
            change() {
                this.a = 5;
            }
        },
        watch: {
            a() {
                console.log('watch a');
            }
        },
        computed:{
            d() {
                console.log('computed');
                return this.a + this.b;
            }
        }
    }
</script>

watch: a属性变化时打印.
computed: (a|b)属性变化时打印.

这个例子change一直都是5,实际上不会一直执行打印,都有缓存.

没看过这方面的源码,但是据说computed的依赖变化的时候如果没对computed里面的值进行使用,好像是不会触发computed的。

commented

没看过这方面的源码,但是据说computed的依赖变化的时候如果没对computed里面的值进行使用,好像是不会触发computed的。

因为computed没有对观察者进行实现,只是做了数据劫持

computed 是在Dep.update(),执行之后,数据更新之前,对新数据从新改造。

watch 是在set刚开始发生的时候添加的回调,可以监听数据的变化情况
commented

我总结了下,有如下几点:

  • 功能上:computed是计算属性,也就是依赖其它的属性计算所得出最后的值。watch是去监听一个值的变化,然后执行相对应的函数

  • 使用上:computed中的函数必须要用return返回;watch的回调里面会传入监听属性的新旧值,通过这两个值可以做一些特定的操作,不是必须要用return

  • 性能上:computed中的函数所依赖的属性没有发生变化,那么调用当前的函数的时候会从缓存中读取,而watch在每次监听的值发生变化的时候都会执行回调

  • 场景上:computed:当一个属性受多个属性影响的时候,例子:购物车商品结算;watch:当一条数据影响多条数据的时候,例子:搜索框

commented

我总结了下,有如下几点:

  • 功能上:computed是计算属性,也就是依赖其它的属性计算所得出最后的值。watch是去监听一个值的变化,然后执行相对应的函数
  • 使用上:computed中的函数必须要用return返回;watch的回调里面会传入监听属性的新旧值,通过这两个值可以做一些特定的操作,不是必须要用return
  • 性能上:computed中的函数所依赖的属性没有发生变化,那么调用当前的函数的时候会从缓存中读取,而watch在每次监听的值发生变化的时候都会执行回调
  • 场景上:computed:当一个属性受多个属性影响的时候,例子:购物车商品结算;watch:当一条数据影响多条数据的时候,例子:搜索框

感觉总结的挺好的,赞

最直接的:computed中定义的是变量,是可展示的,可操作的值,而watch只是一个工具,服务于变量

commented
  • computed是有缓存的,只有相关依赖没有改变,多次访问都是取缓存中的值,不会多次执行,比如有个性能开销很大的属性Value,有一个巨大的数据在遍历的时候里面的值会依赖到属性Value,会多次出发Value的getter,但是有了缓存就之间在缓存里面查。还有使用上必须有return返回值。
  • watch观察和相应Vue实例上的变动,用于观察某一个值取完成较大的业务逻辑,支持对属性的深度遍历监听和立刻执行,

共同点:都是经过依赖收集和派发更新的流程
不同点:
1、计算属性依赖computed watcher、watch监听依赖的是user watcher。
2、定义方式不同,计算属性本质上是get/set形式,即使写成函数形式,Vue底层也会规范化为get/set形式。而watch提供的是一个回调函数。
3、可取消性不同,计算属性一旦依赖,无法取消,也就是说定义后无法更改其get函数,而使用$watch方法实现的监听它返回一个unwatch可随时取消,取消后当数据再次发生变动时,不会再执行我们的回调函数。
4、时效性不同,计算属性属于惰性求值,当依赖的响应式变量更新时,只要我们不主动触发计算属性的getter,它可能永远都不会重新求值。对于watch而言,只要我们的响应式变量发生了变化,就会执行回调函数。
5、依赖变化性,计算属性的依赖可能不固定,每次求值时会重新进行依赖收集,依赖清除,而watch监听的依赖是固定的。

一、
Computed 的响应是 deep 的响应,即在计算过程中用到的对象的属性发生变化,是可以被监听到的。
watch的响应默认是非deep的,deep: false默认。
immediate同理

computed: {
  fullName: function () {
    // this.name 的属性 firstName/lastName 变化时 fullName 会响应。
    return this.name.firstName + ' ' + this.name.lastName
  }
},
watch: {
  name: function () {
    // this.name 的属性 firstName/lastName 变化时不会触发。
  },
  deep: false, // 默认是false
}

二、
watch支持异步设置数据, computed不支持异步计算数据。

三、
watch不支持缓存,监听的数据改变,直接会触发会setter,computed支持

四、watch主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作,可以看作是 computed 和 methods 的结合体;