标签: angular2-changedetection

Angular2变化检测误解 - 用plunker

我正在尝试用Angular2 final完全理解变化检测.

这包括:

  • 处理变更检测策略
  • 从组件上安装和拆卸更换检测器.

我以为我已经对这些概念进行了非常明确的概述,但为了确保我的假设正确,我写了一个小傻瓜来测试它们.

我对全球正确的一般理解,但在某些情况下,我有点迷失.


这是plunker:Angular2变化检测操场

对plunker的快速解释:

很简单:

  • 一个父组件,您可以在其中编辑一个将传递给两个子组件的属性:
  • 将具有变化检测策略的孩子设置为OnPush
  • 将具有更改检测策略的子项设置为"默认"

parent属性可以通过以下任一方式传递给子组件:

  • 更改整个属性对象,并创建一个新对象(" 更改obj "按钮)(触发OnPush子项上的更改检测)
  • 更改属性对象内的成员("更改内容"按钮)(不会触发OnPush子项上的更改检测)

对于每个子组件,可以附加或分离ChangeDetector.("detach()""reattach()"按钮)

OnPush子项具有可以编辑的附加内部属性,并且可以显式应用更改检测("detectChanges()"按钮)


以下是我得到无法解释的行为的场景:

Scenario1:

  1. 分离OnPush Children和Default Children的更改检测器(单击两个组件上的" detach() ")
  2. 编辑父属性firstname和lastname
  3. 单击" 更改obj "将修改后的属性传递给子项

预期的行为: 我希望两个孩子都不会被更新,因为他们都有自己的变化探测器.

当前行为: 默认子项未更新,但OnPush子项已更新.. 为什么? 它不应该因为它的CD分离...

Scenario2:

  1. 为OnPush组件分离CD
  2. 编辑其内部值输入并单击更改内部:没有任何反应,因为CD已分离,因此未检测到更改...确定
  3. 单击detectChanges():检测到更改并更新视图.到现在为止还挺好.
  4. 再一次,编辑内部值输入并单击更改内部:再次,没有任何事情发生,因为CD已分离,因此未检测到更改..确定
  5. 编辑父属性firstname和lastname.
  6. 单击" 更改obj "将修改后的属性传递给子项

预期的行为: OnPush的孩子不应该全部更新,再次因为它的CD被分离...... CD不应该在这个组件上发生

当前行为: 更新值和内部值,将完整CD等接缝应用于此组件.

  1. 最后一次,编辑内部值输入并单击更改内部:检测到更改,并更新内部值...

预期行为: 不应更新内部值,因为CD仍然已分离

当前行为: …

plunker angular2-changedetection angular

8
推荐指数
1
解决办法
1866
查看次数

Angular2使用ApplicationRef手动实现更改检测

获得更改检测错误

检查后表情发生了变化.上一个值:'true'.当前价值:'假'

所以我想手动运行另一轮变化检测.找到有关使用ApplicationRef.tick()但当前收到错误的信息

ERROR在[默认] C:\ development\SolarUI11\src\app\update\update.component.ts:8:11类型'{selector:string; 风格:任何[]; 模板:任何; 提供者:( typeof ApplicationRef | typeof Date ...'不能分配给'Component'类型的参数.属性'provider'的类型是不兼容的.Type'(typeof ApplicationRef | typeof DatePipe)[]'不能赋值给' Provider []'.类型'typeof ApplicationRef | typeof DatePipe'不能分配给'Provider'类型.类型'typeof ApplicationRef'不能分配给'Provider'类型.类型'typeof ApplicationRef'不能分配给'FactoryProvide r'类型类型'typeof ApplicationRef'中缺少属性'provide'

我想我只是坚持实现这个的语法,自己找不到足够的信息才能使用它.

打字稿:

import { Component, Input, ApplicationRef } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import {NgbDateStruct} from '@ng-bootstrap/ng-bootstrap';
import {DatePipe} from "@angular/common";
import { DataTable } from '../data/datatable';
import { DPS } from '../data/datainfo.ts';

@Component({
  selector: 'update-validation',
  styleUrls: ['../app.component.css'],
  templateUrl: 'update.component.html',
  providers: [DatePipe, ApplicationRef]
}) …
Run Code Online (Sandbox Code Playgroud)

typescript angular2-changedetection angular

8
推荐指数
1
解决办法
4846
查看次数

具有大量字段的类/接口对性能有何影响?

我的角度4应用程序中有一个类(界面),它有很多字段.请注意,此类/接口的实例是immutable(即不会更改成员).

例如

public interface IHaveALotOfFields {
    field1: string;
    //...
    field500: string;
}
Run Code Online (Sandbox Code Playgroud)

此接口通过(单例/应用程序级别提供)服务提供,该服务将类作为成员公开.例如

@Injectable()
public class MyService {
    public translations: ITranslationsProvider;
}
Run Code Online (Sandbox Code Playgroud)

该服务被注入许多组件(几乎所有组件),并且经常在其相应的模板中使用,并且通常也在ts组件的部分中使用.例如

@Component({
               template: `Value: {{service.field500}}`
           })
export class MyComponent {
    public constructor(public service: MyService) {
    }

    private doSomething(): string {
        return this.service.field1;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我的问题:

  • 由于变化检测,一个大类(有很多字段)是否会使角度变慢?
  • 有没有办法将课程标记为"忽略我的变化检测"?(类似于ChangeDetectionStrategy.OnPush,但不是为每个组件指定这个,可以在类本身或服务的成员上声明)

请注意,我不想将所有组件的更改检测策略更改为OnPush.

angular2-changedetection angular

8
推荐指数
1
解决办法
255
查看次数

为什么我需要使用默认的更改检测策略调用detectChanges()?

我正在开发一个Angular 4应用程序,但我遇到了一个问题,因为我不得不this.changeDetectorRef.detectChanges();在模型更改时调用更新视图.例如,我有这个用于分页的代码:

changePage(pageNumber) {
  this.currentPage = pageNumber;
  // why do I need to do this?
  this.changeDetectorRef.detectChanges();
}
Run Code Online (Sandbox Code Playgroud)

我已经明确地在组件上设置了更改检测策略,ChangeDetectionStrategy.Default但这没有任何效果.在订阅一个observable时也会发生这种情况:

showResults(preference) {
  this.apiService.get('dining_autocomplete/', `?search=${preference}`)
    .subscribe((results) => {
      this.searchResults = results;
      // why do I need to do this?
      this.changeDetectorRef.detectChanges();
  });
}
Run Code Online (Sandbox Code Playgroud)

如果我console.log() this.searchResults在TypeScript中,我得到了预期的结果,但是如果我{{ searchResults }}在HTML中使用它,它就不会更新,直到其他事件发生,大概是当它经历另一个摘要周期时.

会发生什么事?

==编辑=============================================== ============

我的组件的代码如下所示:

import {ChangeDetectorRef, Component, Input, OnChanges} from "@angular/core";

import * as _ from 'lodash';

@Component({
  selector: 'dining-search-results',
  templateUrl: './dining-search-results.template.html',
  styleUrls: ['./dining-search-results.style.scss'],

})
export class DiningSearchResultsComponent { …
Run Code Online (Sandbox Code Playgroud)

typescript angular2-changedetection angular

8
推荐指数
1
解决办法
2万
查看次数

Angular 5.0变化检测策略VS React的变化检测策略

我理解变量检测Angular 5.0中是如何工作的.

有人可以帮助我理解React中的相同功能以及它与Angular的不同之处什么?

reactjs virtual-dom angular2-changedetection angular

8
推荐指数
2
解决办法
1676
查看次数

Angular Ivy在手动更改检测方面特别允许我们做什么?

本文提到

常春藤为未来打开了一些可能性。现在应该可以在没有zone.js的情况下运行应用程序,并以半手动方式处理变更检测(有点像使用React一样)。这些API已经存在,但只是实验性的,没有记录在案,并且可能会在不久的将来发生变化。

我认为已经可以在Ivy之前运行没有zone.js的应用程序了。常春藤是否允许半手动处理变更检测?这些实验性API在哪里?有文件吗?常春藤仍然使用zone.js吗?

我的目标是通过手动触发更改检测来将更改检测降至最低。这样做的最佳选择是什么。特别是使用常春藤时最好的选择是什么。

zone angular2-changedetection angular angular-ivy

8
推荐指数
1
解决办法
150
查看次数

@HostListener在我正在侦听外部点击时导致更改检测触发次数太多

我有下一个根组件模板,它绘制了9个tile:

<ul>
  <li *ngFor="let x of [0,1,2,3,4,5,6,7,8]">
    <tile></tile>
  </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

和下一个tile组件,我在其中添加了HostListener以进行文档点击:

import {AfterViewChecked, Component, HostListener} from '@angular/core';

@Component({
  selector: 'tile',
  template: '<p>tile works!</p>'
})
export class TileComponent implements AfterViewChecked {

  ngAfterViewChecked(): void {
    console.log('checked');
  }

  @HostListener('document:click', ['$event'])
  onOutsideClick(event: any): void {
      // do nothing ...
  }

}
Run Code Online (Sandbox Code Playgroud)

Plunker:http://plnkr.co/edit/7wvon25LhXkHQiMcwh48?p =preview

当我运行它时,我看到每次点击更改检测被称为9 ^ 2次: 在此输入图像描述

我不明白为什么.

有人可以向我解释为什么在这种情况下变化检测触发n ^ 2次?

angular2-changedetection angular

7
推荐指数
1
解决办法
1519
查看次数

角度:未检测到管道中的更改

我有这个管道,它将输入值乘以从服务检索到的其他值:

@Pipe({
    name: 'multiply'
})
export class MultiplyPipe implements PipeTransform {
    constructor(private service: StateService) { }

    transform(value: any, args?: any): any {
        return value * this.service.multiplier;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

{{ value | multiply }}
Run Code Online (Sandbox Code Playgroud)

DEMO

这工作正常,但是当multiply服务的值发生更改时,它不会触发任何更改检测,因此

 {{ value | multiply }}
Run Code Online (Sandbox Code Playgroud)

不再运行,将旧值保留在屏幕上.有什么建议可以修复吗?

angular2-changedetection angular

7
推荐指数
2
解决办法
1698
查看次数

在模板中使用 Angular Reactive Forms .get() 方法会导致像组件方法一样不必要的方法调用吗?

我知道如果我在模板中使用方法调用,它会一遍又一遍地执行(不理想)。我已经通过使用纯管道和记忆方法的组合解决了这个问题。但我也在使用反应式表单,并在我的模板中使用 myFormGroup.get('myFormControl').value 来获取值。这是否也会像我的组件中的方法一样重复执行,或者 Angular 是否有适当的策略来防止这种情况发生?一个用法示例是使用 *ngIf 并让条件基于表单的值。

此外,我目前没有遇到任何性能下降,但我想在使用此应用程序走得太远之前以最佳方式实现这一点(并且只是好奇)。

我可以轻松地更新它以直接引用表单对象上的属性,我只是更喜欢方法调用的语法。任何见解都会有所帮助,谢谢!

javascript angular2-changedetection angular angular-forms

7
推荐指数
1
解决办法
2976
查看次数

角度更改检测不适用于 HttpClinet.Subscribe 中的 ChangeDetectionStrategy.OnPush

我复制了一个简单的stackblitz,演示了我遇到的问题。问题是我有一个父组件将布尔值传递给子组件。这个布尔值是子组件上的@Input。需要注意的是,父组件使用ChangeDetectionStrategy.OnPush。子组件没有显式设置。

当父组件在订阅方法中更改子组件的布尔输入属性时,子组件最初不会检测到更改。总是需要单击 2 次才能让子组件检测到更改。

但是,当我在订阅方法之外更改子组件的布尔输入属性时,子组件会正确检测到更改,并且一切都会按预期工作(单击 1 次子组件即可识别更改)。

App.Component.ts(父组件)

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent  {
  constructor(private http: HttpClient) {

  }
  public isHelloVisible: boolean;
  public useHttpGet: boolean;

  showHello() {
    if (this.useHttpGet) {
    this.http.get('https://cors-anywhere.herokuapp.com/https://api.darksky.net/forecast/cc0e3799790b0b34bdeb6fef28c3daf7/17.447409200000003,-78.3724573?units=si').subscribe(data => {
      this.isHelloVisible = true;  
    });
    } else {
      this.isHelloVisible = true;
    }
  }

  closeHello() {
    this.isHelloVisible = false;    
  }
Run Code Online (Sandbox Code Playgroud)

子组件(Hello.component.ts)

@Component({
  selector: 'hello',
  template: `<div *ngIf="showHello">
    Hello
    <div (click)="closeHello()">Click me to close Hello</div>
  </div>
  
  `, …
Run Code Online (Sandbox Code Playgroud)

observable angular2-changedetection angular angular-input

7
推荐指数
1
解决办法
1万
查看次数