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

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

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

时间: 2024-08-29 16:28:00

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

[从 0 开始的 Angular 生活]No.38 实现一个 Angular Router 切换组件页面(一)

前言 今天是进入公司的第三天,为了能尽快投入项目与成为团队可用的战力,我正在努力啃官方文档学习 Angular 的知识,所以这一篇文章主要是记录我如何阅读官方文档后,实现这个非常基本的.带导航的网页应用. 需求 需求大概是这样的: 开一个新的 Angular 项目,并且一开始选择加入 Router 功能 根组件是 AppComponent ,然后下方有三个子组件分别是 page1 page2 page3 可以在 AppComponent 内点击连结切换到这三个页面 参考文档: 路由与导航 Rou

初识vue 2.0(13):子组件使用watch监听父组件变化

子组件使用created或者mounted通常只能在组件初始化的时候,获取父组件传过来的props数据. 父组件props数据发生变化,子组件默认无法感知,因此需要手动实现子组件监听父组件变化的功能. 一般的值类型数据,可以直接使用watch监听: watch: { msg(newVal, oldVal){//对引用类型的值无效 console.info('value changed ', newVal) } } 引用类型,普通watch方法,无法监听到引用类型内部的变化. 解决此问题,可以在父

Angular动态创建组件之Portals

这篇文章主要介绍使用Angular api 和 CDK Portals两种方式实现动态创建组件,另外还会讲一些跟它相关的知识点,如:Angular多级依赖注入.ViewContainerRef,Portals可以翻译为 门户 ,我觉得放到这里叫 入口 更好,可以理解为动态创建组件的入口,类似于小程序或者Vue中的Slot. cdk全名Component Development Kit 组件开发包,是Angular官方在开发基于Material Design的组件库时抽象出来单独的一个开发包,里面

Unity3d修炼之路:加载一个预制体,然后为该对象添加组件,然后查找对象,得到组件。

#pragma strict function Awake(){ //加载一个预制体 资源必须在 Resources文件夹下 Resources.LoadLoad(); //加载后 必须示例化 GameObject.Instantiate(); //为对象添加组件 AddComponent(); //Find游戏对象 Find(); //Get组件 GetComponent(); var pPrefab : GameObject = Resources.Load("Prefab/Scence&q

Unity3d修炼之路:载入一个预制体,然后为该对象加入组件,然后查找对象,得到组件。

#pragma strict function Awake(){ //载入一个预制体 资源必须在 Resources目录下 Resources.LoadLoad(); //载入后 必须演示样例化 GameObject.Instantiate(); //为对象加入组件 AddComponent(); //Find游戏对象 Find(); //Get组件 GetComponent(); var pPrefab : GameObject = Resources.Load("Prefab/Scence&

Angular 监听路由变化

var app = angular.module('Mywind',['ui.router']) //Angular 监听路由变化 function run($ionicPlatform, $location, Service, $rootScope, $stateParams) { //路由监听事件 $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) { co

angular 中父组件调用子组件的方法

angular中 父组件调用子组件的方法 -- 使用 @ViewChild 装饰器修饰子组件,获取方法,调用 除此之外 ViewChild 还可以获取 DOM ,操作 DOM , 详见: https://www.cnblogs.com/monkey-K/p/11567098.html 1. html 中使用 #var 方式标记 子组件 <div style="border: 1px solid red"> <p>子组件:</p>> <ap

Angular第三方UI组件库

一.Angular第三方UI组件库(github搜“awesome angular ")-----lonic 概述:是一个第三方的适用于移动端App的UI组件库,可以与Angular/React/Vue.js组合,也可以独立使用. 九种主题色:primary.secondary.tertiary.danger.warning.success.dark.medium.light 2.页面结构:<ion-app> <ion-header> <ion-toolbar>

angular模块和组件之间传递信息和操作流程的方法(笔记)

angular的模块之间,以及controller.directive等组件之间,是相对独立的,用以实现解耦合. 为实现相互之间传递信息及操作流程,有以下一些机制: 1.事件机制: $scope.$broadcast:向下广播事件,下方所有的scope都会接收到这个事件,事件不能中途终止. $scope.$emit:向上冒泡事件,可带参数,一直冒泡到$rootScope,中途可以用stopPropagation()方法终止冒泡. 2.scope的继承机制: 子scope的__proto__对象就