变量检测如何对Angular服务中声明的字符串,数组和对象起作用

时间:2018-01-26 12:44:47

标签: angular typescript

我问这个问题是为了更好地理解变量检测在Angular中的工作原理。

我知道当服务中声明的变量发生变化时,我应该使用RxJS来通知组件。

我感兴趣的是为什么Angular会检测到数组和对象的更改,而不是字符串变量。

这是一个例子

服务在3秒后更改字符串,数组和对象

import { Injectable } from '@angular/core';
@Injectable()
export class NameService {
  name = '';
  list = [];
  obj = {
    a: 'something'
  };

  constructor() {

    setTimeout(() => {
      this.name = 'Name changed';
      this.list.push('a', 'b');
      this.obj.a = 'obj.a changed';
    }, 3000);
  }
}

成分<​​/ P>

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { NameService } from './name.service';

@Component({
  selector: 'my-app',
  template: `
      <div>{{name}}</div>
      <div>{{list | json }}</div>
      <div>{{obj | json }}</div>`,
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  name = '';
  list = [];
  obj = {};

  constructor(private nameService: NameService) { }

  ngOnInit() {

    this.name = this.nameService.name;
    this.list = this.nameService.list;
    this.obj = this.nameService.obj;

  }
}
Angular检测到

listobj更改,但name未检测到。这是否会发生,因为数组和对象是可变的,字符串是不可变的?

您可以使用代码https://stackblitz.com/edit/angular-ch-detec-jzm6r1

1 个答案:

答案 0 :(得分:3)

简单的原因是this.list = this.nameService.list;this.obj = this.nameService.obj;正在为左侧指定一个数组或对象的引用(指针)。

当内容被添加到数组或对对象的值进行更改时,正在更改的是数组/对象的内容而不是指向列表或对象的指针,在这种情况下,这是什么已分配到this.listthis.obj

另一方面,this.name = this.nameService.name;正在为this.name分配确切的值。

那么数据的变化如何传播?

创建组件时,ngOnInit() lifecycle hook仅被调用一次。它是在服务上的值被复制到组件中的变量的时间点,在您的情况下如下所示。

this.name = this.nameService.name;  // The actual value is assigned to this.name
this.list = this.nameService.list;  // The pointer to the list in memory is assigned to this.list
this.obj = this.nameService.obj;    // The pointer to the object in memory is assigned to this.obj

3秒后执行setTimeout回叫功能时,

  1. 服务上name变量的值已更改
  2. 服务上的列表和对象的内容已更新(请注意,指针,调用this.nameService.list/obj 时检索的实际值保持不变
  3. Angular被通知已发生异步事件(当执行setTimeout时)并且运行更改检测周期。
  4. 一旦更改了检测周期,Angular将呈现其拥有的内容。

    如果是name变量,它会呈现静态值。在list/obj的情况下,它读取列表/对象的内容,各个指针(自初始化后引用从未改变)指向并呈现新内容(即已更新的内容)。

    <强>更新: -

    article提供了有关变更检测如何运作的深入应用。