Vue数据双向绑定(Vue data bidirectional binding)

一、vue实现数据双向绑定的主要是:

采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter、getter,在数据变动时发布消息给订阅者,触发相应监听回调。

当创建Vue实例时,vue会遍历data选项的属性,利用Objet.defineProperty为属性添加getter和setter对数据的读取进行劫持(getter用来依赖收集,setter用来派发更新),并且在内部追踪依赖,在属性被访问和修改时通知变化。

每个组件实例会有对应的watcher实例,在组件渲染的过程中记录依赖的所有数据属性(进行依赖收集,还有computed watcher,user watcher实例),之后依赖项被该改动时,setter方法会通知依赖与此data的watcher实例重新计算(派发更新),从而使它关联的组件重新渲染。

二、单向数据绑定流和双向数据绑定

1. 单向数据绑定:数据流是单向的。

优点:数据流动方向可以追踪,流动单一,追查问题的时候可以更快捷。

缺点:写起来不太方便。要使UI发生变更就必须创建各种action来维护对应的state

2.双向数据绑定:数据之间是相通的,将数据变更的操作隐藏在框架内部。

优点:在表单交互较多的场景下,会简化大量与业务无关的代码。

缺点:无法追踪局部状态的变化,增加了出错时debug的难度。

三、为什么在Vue3.0采用了Proxy,抛弃了Object.defineProperty

Object.defineProperty本身有一定的监控到数组下标变化的能力,但是在Vue中,从性能/体验的性价比考虑,弃用了这个特性(Vue为什么不能检测数组的变动)。为了解决这个问题,经过Vue内部处理后可以使用以下几种方法来监听数组

push()、pop()、shift()、unshift()、splice()、sort()、reverse()

由于只针对了以上7种方法进行了hack处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。

Object.defineProperty只能劫持对象的属性,因此需要对每个对象的每个属性进行遍历。Vue 2.x是通过递归+遍历data对象来实现对数据的监听的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象才是更好的选择。Proxy可以劫持整个对象,并返回一个新的对象。Proxy不仅可以代理对象,代理数组。还可以代理动态增加的属性。

四、Proxy相较于Object.defineProperty的优势

1.直接监听对象而非属性

2.直接监听数组的变化

3.拦截方式较多

4.Proxy返回一个新对象,可以只操作新对象达到目的,而Object.defineProperty只能遍历对象属性直接修改(需要用深拷贝进行修改)

5.Proxy作为新标准将受到浏览器厂商重点持续的性能优化

6.Proxy不能用polyfill来兼容,polyfill主要抚平不同浏览器之间对js实现的差异。

————————

1、 Vue mainly realizes two-way data binding:

Data hijacking combined with publisher subscriber mode is adopted through object Defineproperty () hijacks setters and getters of various properties, publishes messages to subscribers when data changes, and triggers corresponding listening callbacks.

When creating a Vue instance, Vue will traverse the attributes of the data option, using objet Defineproperty adds getters and setters to the property to hijack the reading of data (getters are used to rely on collection and setters are used to distribute updates), tracks the dependency internally, and notifies changes when the property is accessed and modified.

Each component instance will have a corresponding watcher instance. In the process of component rendering, record all the dependent data attributes (including dependency collection, calculated watcher and user watcher instances). Then, when the dependency is changed, the setter method will notify the watcher instance that depends on this data to recalculate (send updates), so as to make its associated components re render.

2、 Unidirectional data binding flow and bidirectional data binding

1. Unidirectional data binding: the data flow is unidirectional.

Advantages: the data flow direction can be tracked, the flow is single, and the problem can be traced more quickly.

Disadvantages: it is not convenient to write. To change the UI, you must create various actions to maintain the corresponding state

2. Bidirectional data binding: data are interlinked, and the operation of data change is hidden inside the framework.

Advantages: in the scenario of more form interaction, a large number of code irrelevant to business will be simplified.

Disadvantages: the change of local state cannot be tracked, which increases the difficulty of debugging in case of error.

3、 Why in vue3 0 adopts proxy and discards object defineProperty

Object. Defineproperty itself has a certain ability to monitor the changes of array subscripts, but in Vue, this feature is abandoned in consideration of performance / experience cost performance (why can’t Vue detect the changes of array). To solve this problem, Vue can use the following methods to listen to arrays after internal processing

push()、pop()、shift()、unshift()、splice()、sort()、reverse()

Because hacking is only carried out for the above seven methods, the properties of other arrays can not be detected, which still has some limitations.

Object. Defineproperty can only hijack the properties of objects, so you need to traverse each property of each object. Vue 2. X monitors the data by recursion + traversing the data object. If the attribute value is also an object, it needs deep traversal. Obviously, it is a better choice to hijack a complete object. Proxy can hijack the whole object and return a new object. Proxy can not only proxy objects, but also proxy arrays. You can also dynamically add attributes to agents.

4、 Proxy compared to object Advantages of defineproperty

1. Directly listen to the object instead of the attribute

2. Directly monitor the changes of the array

3. There are many interception methods

4. Proxy returns a new object. You can only operate the new object to achieve the purpose, but object Defineproperty can only be modified directly by traversing object properties (it needs to be modified with deep copy)

5. As a new standard, proxy will be continuously optimized by browser manufacturers

6. Proxy cannot be compatible with Polyfill, which mainly smoothes the differences in JS implementation between different browsers.