微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

角度变化检测过程重新绘制dom

我正在学习Angular变化检测过程并检查Chrome中的开发工具,我看到了奇怪的行为.

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

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

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

和构造函数

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

模拟我添加的简单请求:

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

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

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

但是值是相同的,为什么角度每2秒重复一次DOM.?

但是如果我改变对象,则不会发生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链接进行测试.

解决方法

这是因为Angular使用认的trackByFunction来跟踪按标识跟踪项目的DefaultIterableDiffer.
const trackByIdentity = (index: number,item: any) => item;

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

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

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

@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就不会更新.见this plunker.

既然你是关于ng的好奇心,你也可以阅读this answer,其中我解释了ngFor如何工作.

原文地址:https://www.jb51.cc/html/231516.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐