欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

angular 有关侦测组件变化的 ChangeDetectorRef 对象 有大用

标签:存在   .com   比较   ref   cor   性能问题   str   取消   box   

我们知道,如果我们绑定了组件数据到视图,例如使用 <p>{{content}}</p>,如果我们在组件中改变了content的值,那么视图也会更新为对应的值。

angular 会在我们的组件发生变化的时候,对我们的组件执行变化检测,如果检测到我们的数据发生了变化,就会执行某些操作,如修改绑定数据的时候更新视图。

这样一来,当我们的组件数据比较多的时候,angular就会有很多操作在静悄悄地进行,一个规避这个问题的方法是,设置某个组件的变化检测策略为 ‘OnPush‘。

使用 OnPush 会指引 angular 去检测那些引用发生变化的对象,而不是某个对象下的属性发生变化就执行变化检测的操作。

 

该方法有以下几个方法:

class ChangeDetectorRef {

  markForCheck(): void

  detach(): void

  detectChanges(): void

  checkNoChanges(): void

  reattach(): void

}

class ChangeDetectorRef {
  markForCheck(): void
  detach(): void
  detectChanges(): void
  checkNoChanges(): void
  reattach(): void
}
       

 

detach 和 reattach

先来说 detach 和 reattach,顾名思义,顾名思义... 只可意会

detach 方法的用处是,告诉 angular,暂时不用管当前组件的变化了,也就是说,当我们在组件上调用 ChangeDetectorRef  的 detach 方法之后,angular 在该组件数据发生变化的时候,不再执行更新视图等操作。

相反的,reattach 就是让 angular 在组件数据发生变化的时候重新检测该组件的变化,在该组件数据变化的时候,执行如更新视图的操作。

import {ChangeDetectorRef, Component} from ‘@angular/core‘;


class DataProvider {

  data = 1;


  constructor() {

    setInterval(() => {

      this.data = this.data * 2;

    }, 500);

  }

}


@Component({

  selector: ‘live-data‘,

  inputs: [‘live‘],

  template: ‘Data: {{dataProvider.data}}‘

})

export class LiveData {

  constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {}


  set live(value) {

    if (value) {

      this.ref.reattach();

    } else {

      this.ref.detach();

    }

  }

}


@Component({

  selector: ‘app-root‘,

  providers: [DataProvider],

  template: `

    Live Update: <input type="checkbox" [(ngModel)]="live">

    <live-data [live]="live"></live-data>

  `,

})

export class AppComponent {

  live = true;

}

import {ChangeDetectorRef, Component} from ‘@angular/core‘;

class DataProvider {
  data = 1;

  constructor() {
    setInterval(() => {
      this.data = this.data * 2;
    }, 500);
  }
}

@Component({
  selector: ‘live-data‘,
  inputs: [‘live‘],
  template: ‘Data: {{dataProvider.data}}‘
})
export class LiveData {
  constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {}

  set live(value) {
    if (value) {
      this.ref.reattach();
    } else {
      this.ref.detach();
    }
  }
}

@Component({
  selector: ‘app-root‘,
  providers: [DataProvider],
  template: `
    Live Update: <input type="checkbox" [(ngModel)]="live">
    <live-data [live]="live"></live-data>
  `,
})
export class AppComponent {
  live = true;
}
       

 

技术分享图片        

上面的例子中,当我们勾中 checkbox 的时候,会发现,右边的数字一直在更新,而当我们取消勾选的时候,数字停止了更新。

也就是说,当我们 detach 的时候,angular 从变化检测树上移除了该组件,reattach 的时候,angular 把该组件重新加到了变化检测树上。

 

 

markForCheck

(调用 markForCheck 方法后,(即使没有输入,也没有事件发射的情况下)会进行脏值检测)

(method) ChangeDetectorRef.markForCheck(): void

When a view uses the {@link ChangeDetectionStrategy#OnPush OnPush} (checkOnce) change detection strategy, explicitly marks the view as changed so that it can be checked again.


Components are normally marked as dirty (in need of rerendering) when inputs have changed or events have fired in the view. Call this method to ensure that a component is checked even if these triggers have not occured.


<!-- TODO: Add a link to a chapter on OnPush components -->




说到这个就不得不说一说 angular 的 ChangeDetectionStrategy 了,参见另外一篇文章:todo        

当我们调用 ChangeDetectorRef  的 markForCheck 方法之后,angular 会在变化检测周期中检测该组件,

如果我们设置了组件的 changeDetection 为 OnPush 的时候,不使用 markForCheck 方法我们更新数据视图是不会更新的。

@Component({

  selector: ‘cmp‘,

  changeDetection: ChangeDetectionStrategy.OnPush,

  template: `Number of ticks: {{numberOfTicks}}`

})

export class Cmp {

  numberOfTicks = 0;


  constructor(private ref: ChangeDetectorRef) {

    setInterval(() => {

      this.numberOfTicks++;

     // 如果我们不调用下面这一句,视图将不会更新

      this.ref.markForCheck();

    }, 1000);

  }

}


@Component({

  selector: ‘app-root‘,

  changeDetection: ChangeDetectionStrategy.OnPush,

  template: `<cmp></cmp>`

})

export class App {}

@Component({
  selector: ‘cmp‘,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `Number of ticks: {{numberOfTicks}}`
})
export class Cmp {
  numberOfTicks = 0;

  constructor(private ref: ChangeDetectorRef) {
    setInterval(() => {
      this.numberOfTicks++;
     // 如果我们不调用下面这一句,视图将不会更新
      this.ref.markForCheck();
    }, 1000);
  }
}

@Component({
  selector: ‘app-root‘,
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `<cmp></cmp>`
})
export class App {}
       

  

detectChanges

检查一遍 变化检测器 (change detector)  和它的子检测器。

可以配合 ChangeDetectorRef 来实现局部变化检查。

有些時候,对于更新频繁数据量又很大的列表,我们不想 angular 在列表变化的时候马上更新视图,我们可以手动去调用 detectChanges 方法,去强制 angular 检查 组件数据的变化。

这样一来,就可以实现自主控制视图更新频率,而不用担心有太大的性能问题了。

 

checkNoChanges

检测该组件及其子组件,如果有变化存在则报错,用于开发阶段二次验证变化已经完成。

 

angular 有关侦测组件变化的 ChangeDetectorRef 对象    

标签:存在   .com   比较   ref   cor   性能问题   str   取消   box   

原文:https://www.cnblogs.com/eleven24/p/8370527.html


来自  http://www.bubuko.com/infodetail-2477822.html


angular2 ChangeDetectorRef (变化检测器的引用)手动控制组件的变化检测行为

Angular检测机制

  监测到异步事件后是怎么判断是否需要更新视图呢?其实比较简单,Angular通过脏检查来判断是否需要更新视图。脏检查其实就是存储所有变量的值,每当可能有变量发生变化需要检查时,就将所有变量的旧值跟新值进行比较,不相等就说明检测到变化,需要更新对应视图。当然,实际情况肯定不是这么简单,Angular会通过自己的算法来对数据进行检查,对算法感兴趣的可以参考这篇文章-Angular的脏检查算法。
  Angular 应用是一个响应系统,首次检测时会检查所有的组件,其他的变化检测则总是从根组件到子组件这样一个从上到下的顺序开始执行,它是一棵线性的有向树,任何数据都是从顶部往底部流动,即单向数据流。

如何手动执行变更检测

从@angular/core引入AfterViewInit, ChangeDetectorRef。注入ChangeDetectorRef对象

constructor(private todoService:TodoService, private cdr: ChangeDetectorRef){}

它提供了以下方法供我们调用:

复制代码
class ChangeDetectorRef {
  markForCheck(): void
  detach(): void
  detectChanges(): void
  checkNoChanges(): void
  reattach(): void
}
复制代码
  • markForCheck() - 在组件的 metadata 中如果设置了 changeDetection: ChangeDetectionStrategy.OnPush 条件,那么变化检测不会再次执行,除非手动调用该方法。


    • 复制代码
      @Component({
        selector: 'app-refer',
        templateUrl: './refer.component.html',
        styleUrls: ['./refer.component.css'],
        changeDetection: ChangeDetectionStrategy.OnPush
      })
      复制代码

       

  • detach() - 从变化检测树中分离变化检测器,该组件的变化检测器将不再执行变化检测,除非手动调用 reattach() 方法。

  • reattach() - 重新添加已分离的变化检测器,使得该组件及其子组件都能执行变化检测

  • detectChanges() - 从该组件到各个子组件执行一次变化检测

  手动设置变更检测:
ref.detach();
setInterval(() => {
 this.ref.detectChanges();
}, 5000);

 


详情链接:https://www.jianshu.com/p/6bef681a0cae


来自  https://www.cnblogs.com/hjsblogs/p/10418764.html

普通分类: