vuecomputed(vuecomputed和watch)
Vue之computed
computed:(多对一个computed变量)
1.computed用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义
2.computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化。例如,通过多个input输入值去改变按钮是否可以点击
watch:(一个watch对多)
1.watch主要用于监控vue实例的变化,它监控的变量当然必须在data里面声明才可以
计算属性是基于它们的依赖进行缓存的,而方法是不会基于它们的依赖进行缓存的。从而使用计算属性要比方法性能更好。
当你需要在template中根据参数显示不同的数据,那么就可以使用computed,如果使用的是methods就会导致每次渲染加载,影响页面加载效率
Vue中computed计算属性的使用和三个特点
computed是Vue实例中的一个属性对象。
在computed中,可以定义一些属性,这些属性,叫做计算属性。计算属性的本质就是一个方法,只不过,我们在使用这些计算属性的时候,是把它们的名称,直接当做属性来使用,并不会把计算属性当做方法来使用。
三个注意事项:
一、计算属性在引用的时候,一定不要加()去调用,直接把它当作普通的属性去使用就好了;
二、只要计算属性这个function内部所用到的data中的数据发生了变化,就会立即重新计算这个计算属性的值;
三、计算属性的求值结果,会被缓存起来,方便下次继续使用;如果计算属性方法中,所依赖的任何数据,都没有发生过变化,则不会重新对计算属性求值。
Vue computed 实现原理
1、每个computed属性都会生成对应的Watcher实例,watcher拥有value属性和get方法,computed的getter函数会在get方法中调用,并返回赋值给value。初始设置dirty和lazy为true,当lazy为true时不会立即执行get方法,而是会在读取computed值时执行;
2、将computed属性添加到组件实例上,通过get、set进行属性值的获取或设置,并且重新定义getter方法;
3、页面初始化时,会读取computed属性值,触发重新定义的getter,由于观察者的dirty值为true,将会调用原始的getter函数,当getter方法读取data数据时会触发原始的get方法(数据劫持中的get方法),将computed对应的watcher添加到data依赖收集器(dep)中。观察者的get方法执行完后,更新观察者的value,并将dirty置为false,表示value值已更新,之后执行观察者的depend方法,将上层观察者也添加到getter函数中data的依赖收集器(dep)中,最后返回computed的value值;
4、当更改了computed属性getter函数依赖的data值时,将会触发之前dep收集的watcher,依次调用watcher的update方法,先调用computed的观察者的update方法,由于lazy为true,会将dirty先设置为true,表示computed属性getter函数依赖data发生变化,但不调用观察者的get方法更新value值。这时调用包含更新页面方法的观察者的update方法,在更新页面时会读取computed属性值,触发重新定义的getter函数,由于dirty为true,调用该观察者的get方法,更新value并返回,完成页面渲染;
Vue中computed与watch何时使用
computed被叫做计算属性:
1.在页面中使用大量或是复杂的表达式去处理数据,对页面的维护会有很大的影响。这个时候就需要用到computed 计算属性来处理复杂的逻辑运算,这样在页面中就可以简单的写成{{bookmark}},computed一般是改变data或者props里面的值为己用。
2.computed的值不可以在data中定义和赋值
watch被叫做侦听器:
1.虽然计算属性在大多数情况下是非常适合的,但是在有些情况下我们需要自定义一个watcher,当需要在数据变化时执行异步或开销较大的操作时,这时watch是非常有用的。
在这个示例中,使用 watch 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
2.watch可以进行深度监听,监听对象的变化。
如果我们要监听group的data1的变化
里面的deep设为了true,这样的话,如果修改了这个group中的任何一个属性,都会执行handler这个方法。不过其实这样开销是蛮大的,尤其是对象里面结构嵌套过深的时候。而且有时候我们就想关心这个对象中的某个属性,比如data3,这个时候可以这样:
有不完美之处欢迎大家多提意见~~
vue2中computed原理
要理解这个,首先要理解vue2的数据响应式原理,因为computed这个API的实现是建立在数据响应式的基础之上的。
这里附上vue响应式原理的地址: vue2数据响应式原理
在vue的watcher实例中配置了lazy,dirty,value属性,就是用来配合实现computed的API。vue在初始化computed时,会给每一个computed属性配置一个watcher,并配置lazy的值为true。在new Watcher时,还会设置dirty为true。由于lazy为true,这个时候并不会执行computed配置的get方法,也就是说不会去计算出这个计算属性的值出来,那么什么时候才计算呢?就是在执行render函数时,会去取计算属性的值,这个时候,会执行计算属性的getter。在getter里面,会先判断dirty的值(为true,则表示当前计算属性的值为脏值,已经过期了,需要重新计算出来;为false则表示当前的值是最新的,不需要重新计算,直接取缓存里面的值就行了,也就是value字段的值)。如果为true,则调用watcher.evaluate方法计算最新的值出来,然后将dirty设为false,把最新的值赋值给value。在计算最新的值时,也就是执行我们在computed对象中配置的相应的get函数。根据之前讲的响应式原理,会先将当前的watcher挂到dep的静态属性target上,然后执行get,在这个过程中,会使用到data中的属性,然后进行依赖收集,将computed的watcher存到data数据对应的dep中去。完了之后,将watcher从targetStack中弹出,这是dep的静态属性target的值又变成了render函数的watcher。以上步骤执行完后,会判断当前dep的target是否还有值,有的话,会执行watcher.depend()。这一步是为了让依赖的data对应的dep中不仅是收集到computed的wathcer,还要收集render函数的watcher,因为当我们依赖的data改变时,不仅要通知到computed的watcher,还要通知render函数的watcher,达到重渲染的目的。然后会把最新的value值返回,这时,render函数里面终于拿到了计算属性的最新值了。假如后面继续用到了这个计算属性,那么在执行计算属性的getter时,跟之前一样,会先判断dirty值,这个时候,dirty的值为false,则直接返回value值,也就是之前说的取缓存的值,不会再次运行一遍计算属性的get函数了。
当某个时候,计算属性依赖的data数据变了,则会先后触发computed的watcher,还有render函数的watcher。在将vue的数据响应式原理时,我们知道,数据改变时,是会触发watcher的update方法。在这个方法里面,首先判断lazy是否为true,这就是针对计算属性设计的。我们可以看看源码片段:
如果为true,则只做了一件非常简单的事,就是把dirty设为了true,然后就没了。这个时候会去执行render函数的watcher.update。也就是把render函数的执行交给了nextTick去管理,这也是之前讲过的。在执行render函数时,又使用到了这个计算属性,那么,则会执行这个计算属性的getter,判断dirty是否为true,由于刚刚在执行computed的wathcer.update时,把dirty设为了true,这个时候肯定会执行watcher.evaluate重新去计算最新的值,也就是执行我们配置在computed里面的get函数。接下来的其实跟前面所讲的都是一样的了。
这里附上关于computed初始化的源码片段:
以上就是个人对于computed原理的理解了。