一、vue中computed和watch区别?
- computed
- 计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
- 注意如果你为一个计算属性使用了箭头函数,则
this
不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。 - 计算属性的结果会被缓存,除非依赖的响应式 property 变化才会重新计算。如果某个依赖 (比如非响应式 property) 在该实例范畴之外,则计算属性是不会被更新的。
- watch
- 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用
$watch()
,遍历 watch 对象的每一个 property。在watch中使用箭头函数绑定时,应注意this的指向。
- 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用
区别:
- watch顾名思义,用于监听数据变化,其中可以监听的数据来源有三部分:props、data、computed内的数据;watch提供两个参数(newValue,oldValue),第一个参数是新值,第二个参数保存旧值;
- 而computed用于处理复杂的逻辑运算,主要和methods储存方法来进行区分;methods储存方法,computed储存需要处理的数据值;methods每次都会调用,computed有缓存机制,只有改变时才执行,性能更佳;
- computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化,举例:购物车里面的商品列表和总金额之间的关系,只要商品列表里面的商品数量发生变化,或减少或增多或删除商品,总金额都应该发生变化。这里的这个总金额使用computed属性来进行计算是最好的选择
计算属性的特点
计算属性computed
- 支持缓存,只有依赖数据发生改变,才会重新进行计算
- 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
- computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过的数据通过计算得到的
- 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
- 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
- computed里的属性的值可以是一个对象,这个对象里有两个方法,get 和 set ,当我们调用这个属性的时候,默认会走get,所以这时候还可以对读取的值做最后的设置,但是千万注意,不要在这里面修改计算属性本身,不然会死循环哦~,如果 get 方法里面有定时器之类的话是会直接报错的,set 方法里没问题,在没有 set 方法的前提下直接修改计算属性也会报错
侦听属性watch的特点:
- 不支持缓存,数据变,直接会触发相应的操作;
- watch支持异步;
- 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
- 当一个属性发生变化时,需要执行对应的操作;一对多;
- 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作
watch还有两个属性
- immediate:组件加载立即触发回调函数执行,
- deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变。
Tips: deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到 当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。这是和computed最大的区别
Watch源码的工作流程:
1.初始化组件上配置的watcher属性
2.对watcher属性可能的写法进行规整,得出key和handle
3.通过new Watcher 来创建一个基于key和handle的观察者
4.Watcher 的key为响应式的vm 上的变量,在watcher.get的时候,watcher订阅了对应key的变化。完成响应依赖。
5.当key的值发生了变化,触发watcher的更新方法,并执行回调函数handle
computed源码的流程:
1.初始化的时候会获取computed里的定义。
2.通过遍历第一步的结果,按照computed新的变量名生成Watcher实例。
3.computed的watcher默认是lazy模式的,所以new Watcher 的时候不会调用watcher实例的get方法
4.vue 为computed 里的每个key 代理了一个新的get方法createComputedGetter(),当render页面的时候,新的get调用computed watcher实例的默认get方法。
5.computed执行自定义get方法的时候,会判断是否依赖又变动,没有的话,直接取值,否则去执行获取依赖的变量。
6.获取依赖变量的时候,将computed的watcher实例订阅到依赖的变量的Dep里。
7.走完这一步后,再调用计算列的watcher.depend将组件的watcher实例也订阅到计算列依赖的所有变量的dep中。
8.这样,当变量变化后,会通知computed的watcher将dirty设置为true, 以及组件的watcher更新dom。
Tips:
1.watcher 初始化是不执行的,如果想初始化就执行的话可以配置immediate属性
2.一般情况不要直接修改computed的值,会报错,一般通过为computed属性自定义set方法,通过改变依赖变量来改变computed的值
3.computed的属性如果不加入在dom中渲染是不会被加入到响应系统的。所以如果只是数据的变动的监控,不映射到dom上,请使用watcher或者其他方法。
4.watcher和computed 属性定义的函数不能使用箭头函数,否则内部this会指向组件的父环境,比如window,导致调用失败
二、React 的组件间通信都有哪些形式?
- 父组件向子组件通信 属性传值—-> props接受
- 子组件向父组件通信 事件传递—-> 回调事件
- 跨级组件之间通信 context全局大容器—->相应组件获取其内容 或者第三方库redux等
非嵌套组件间通信 可以使用自定义事件的方式和context 或者第三方库redux等
使用 context 也很简单,需要满足两个条件:
父组件需要声明自己支持 context,并提供 context 中属性的 PropTypes
- 子组件需要声明自己需要使用 context,并提供其需要使用的 context 属性的 PropTypes
- 父组件需提供一个 getChildContext 函数,以返回一个初始的 context 对象
- 如果组件中使用构造函数(constructor),还需要在构造函数中传入第二个参数 context,并在 super 调用父类构造函数是传入 context,否则会造成组件中无法使用 context。