Angular 脏值检测

Angular变更检测的周期

  1. 开发人员更新数据模型,例如通过更新组件绑定
  2. angular 检测变化
  3. 变更检测从上到下检查组件树中的每个组件,以查看相应的模型是否已更改
  4. 如果有新值,它将更新组件的视图(DOM)

我们分步骤来讲:

Angular使用Zone.js跟踪拦截异步任务。当发生任何用户事件,计时器,XHR,promise等, 回调会触发检测。

变更检测策略

Angular提供了两种策略来运行更改检测:

  • Default(从上到下检查组件树中的每个组件)
  • OnPush (当输入属性已更改/该组件或其子组件触发事件处理/通过异步管道链接到模板的可观察对象发出新值, 如 data | async/手动触发时触发检测。 当settimeout, setInterval, Promise.resolve().then(),this.http.get('..').subscribe()不会触发变更检测

手动触发检测的方法

  • ChangeDetectorRef的detectChanges() 通过牢记更改检测策略在此视图及其子级上运行更改检测。它可以与detach() 结合使用以实现本地更改检测检查。(说明: detach()停用变更检测)
  • ApplicationRef.tick() 通过遵守组件的更改检测策略来触发整个应用程序的更改检测
  • ChangeDetectorRef上的markForCheck() 不会触发更改检测,但会将所有OnPush祖先标记为要检查一次,作为当前或下一个更改检测周期的一部分。即使已标记的组件使用OnPush策略,它也将运行更改检测。

Vue 数据劫持

Vue 的响应式,是使用观察者模式实现的。Vue 会遍历 data 数据对象,使用 Object.defineProperty() 将每个属性都转换为 getter/setter。(Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因)
每个 Vue 组件实例都有一个 watcher 实例,在组件初次渲染(render)时,会记录组件用到了(调用 getter)哪些数据。当数据发生改变时,会触发 setter 方法,并通知所有依赖这个数据的 watcher 实例,然后 watcher 实例调用对应组件的 render 方法,生成一颗新的 vdom 树,Vue 会将新生成的 vdom 树与上一次生成的 vdom 树进行比较(diff),来决定具体要更新哪些 dom。

  

对象对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如,对于:
Vue.set(vm.someObject, 'b', 2)
数组

Vue 不能检测以下数组的变动:当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue, vm.items.length = newLength

触发方法,例如:

Vue.set(vm.items, indexOfItem, newValue); // Vue.set, vm.$set


vm.items.splice(indexOfItem, 1, newValue); // splice

 

其它特征

1、由于 Vue 不允许动态添加根级响应式 property,所以你必须在初始化实例前声明所有根级响应式 property,哪怕只是一个空值。

2、异步更新队列。Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.thenMutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

参考官网介绍 vuejs reactivity


React 虚拟DOM

React 的响应式,是使用 diff 算法实现的。React 在 state 或 props 改变时,会调用 render() 方法,生成一个虚拟 DOM 树,React 会将这棵树与上一次生成的树进行比较,找出其中的差异,并更新差异的部分。

这个过程是递归的,React 会以当前组件为根,递归比较所以子节点。为了优化性能,React 提供了 shouldComponentUpdate 生命周期方法,如果这个方法返回 false,React 就跳过这个组件,不做 VDOM 比较,也不更新组件。

在 React 的世界里,术语 “Virtual DOM” 通常与 React 元素关联在一起,因为它们都是代表了用户界面的对象。而 React 也使用一个名为 “fibers” 的内部对象来存放组件树的附加信息。上述二者也被认为是 React 中 “Virtual DOM” 实现的一部分。

 


 

 

 

Logo

前往低代码交流专区

更多推荐