zoukankan      html  css  js  c++  java
  • angular 有关侦测组件变化的 ChangeDetectorRef 对象

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

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

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

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

    该方法有以下几个方法:

    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;
    }
    

     

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

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

    markForCheck

    说到这个就不得不说一说 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 {}
    

      

    detectChanges

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

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

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

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

    checkNoChanges

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

  • 相关阅读:
    CSS的margin塌陷
    css white-space
    float的理解
    html标签元素分类
    Sublime text3使用技巧及快捷键
    JSON
    js原生Ajax的封装与使用
    XMLHttpRequest基础知识
    HTTP的一些基础知识
    创建兼容的XHR对象
  • 原文地址:https://www.cnblogs.com/eleven24/p/8370527.html
Copyright © 2011-2022 走看看