重绘dom的角度变化检测过程 [英] Angular change detection process repainting the dom

查看:89
本文介绍了重绘dom的角度变化检测过程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习Angular更改检测过程,正在检查Chrome开发工具,发现奇怪的行为.

I'm learning about Angular change detection process and I'm checking the Chrome dev tools, I see strange behavior.

我的plnkr演示了该行为: http://plnkr.co/edit/cTLF00nQdhVmkHYc8IOu

My plnkr to demonstrate the behavior: http://plnkr.co/edit/cTLF00nQdhVmkHYc8IOu

我有一个简单的组件视图:

I have a simple component view:

<li *ngFor="let item of list">{{item.name}}</li>

及其构造函数:

constructor() {
    this.list = [{name: 'Gustavo'}, {name: 'Costa'}]

模拟一个我添加的简单请求:

to simulate a simple request I've added:

// simulating request repaint the DOM
setInterval( () => {
  this.list = [{name: 'Gustavo'}, {name: 'Costa'}];
}, 2000);

如果您注意到了,数组list会收到一个等于初始值的列表.想象一下,当Angular在变更检测过程中检查视图中的值时,我们有这样的代码:

If you noticed, the array list receives a list equal to the initial value. Let's imagine when Angular checks the values in view in change detection process we have a code like this:

if( oldName !== name )  { // ( 'Gustavo' !== 'Gustavo')
 // update the view
}

但是这些值是相同的,为什么每2秒钟有角度地对DOM进行一次修复??

But the values are the same, why angular REPAINT THE DOM every 2 seconds.?

但是如果我对该对象进行了突变,则不会发生REPAINT

// simulating request there is not repaint
setInterval( () => {
  this.list[0].name = "Gustavo"; // no repaint because it's the same value
  this.list[1].name = "Costa 2"; // repaint
}, 2000);

您可以使用上面的plnkr链接对此进行测试.

You can test this with the plnkr link above.

推荐答案

这是因为Angular对DefaultIterableDiffer使用默认的trackByFunction来按身份跟踪项目.

This is because Angular uses default trackByFunction for the DefaultIterableDiffer that tracks items by identity.

const trackByIdentity = (index: number, item: any) => item;

因此,很明显,当您创建一个新数组时,它将创建新的对象引用,并且Angular会检测到更改.即使您没有更改数组引用,Angular仍然会认为项目已更改,因为对象引用会更改:

So obviously when you create a new array it creates new object references and Angular detects changes. Even if you didn't change array reference, Angular will still think that items are changed because object references change:

setInterval( () => {
  this.list.length = 0;
  this.list.push({name: 'Gustavo'});
  this.list.push({name: 'Costa'});
}, 2000);

您可以为您提供自定义的trackByFunction,以按对象名称进行跟踪:

You can provide you custom trackByFunction to track by object name:

@Component({
  selector: 'my-app',
  template: `
   <li *ngFor="let item of list; trackBy:identify">{{item.name}}</li>
  `
})
export class App {
  list:[];

  identify(index, item){
     return item.name; 
  }

这样,将不会更新DOM.参见此小车.

In this way the DOM will not be updated. See this plunker.

由于您对ngFor感兴趣,因此您也可以阅读此答案,在此我将解释ngFor的工作原理引擎盖.

Since you are curios about ngFor you can also read this answer where I explain how ngFor works under the hood.

这篇关于重绘dom的角度变化检测过程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆