标签归档angular

ng2-ExpressionChangedAfterItHasBeenCheckedError

吴阳 No Comments

ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked on ng 4

值在checked完毕后却发生了变化的官方说明,以下内容引自Angular-issue-17572

This seems to keep going on and on even though all of the answers and advice has already been posted above.
1.The right way to fix this is to re-architect/restructure your components and data handling to work with a single change detection pass from the top down. This means that no child component may change a value that is used in the template of a parent component. Re-evaluate what you have built and verify that the data flows only in one direction, down the component tree. This may be as simple as moving your code out of ngAfterViewInit and into ngOnInit in some cases.
2.this.changeDetectorRef.detectChanges(); is the official and recognized way for handling this in the less than 5% of cases where the first step is problematic.

Other notes:
1.Be very careful when doing anything in ngAfterViewInit as changing values that are used in the DOM can cause this error.
2.Be very careful when using any of the Check or Checked lifecycle hooks as they may be called on every change detection cycle.
3.setTimeout can work around this, but the two solutions above are preferred.
4.Ignoring this error in dev mode and being happy that production mode “fixes” the error is not valid as explained above. These checks are not made in prod mode, but your prod mode code is still leaving changes undetected and causing the view and data to be out of sync. This can be harmless in some cases, but can lead to data/view corruption and worse problems if ignored.
5.One way data flow hasn’t really changed a lot in Angular, so posting that you hit this in version X of Angular isn’t too helpful.
6.Adding more lifecycle hooks or states is not a solution to this. Developers would just add code that violates one way data flow into those hooks and trigger this same error.

Finally, just remember that this error is not indicating a problem with Angular. This error is here to let you know that you have done something wrong in your code and that you are violating the one way data flow system that makes Angular fast and efficient.

The posts above and many blog posts go more deeply into this and are worth reading as you should understand this one way data flow model and how to build components and pass data within it.

ng2-NgZone和Renderer2

吴阳 One comment

在Angular中使用Echart为何cpu占用高
了解NgZone

import {  NgZone, Renderer2 } from '@angular/core';
// Renderer2 实验性功能

{
    this._renderer.setStyle(dom, 'width', width);
    this._renderer.setStyle(dom, 'height', height || 'auto');

    // 将echart的初始化脱离NgZone的监控,以免造成大量的cpu占用
    this._zone.runOutsideAngular(() => {
      this.chartInstance = this.chartInstance || echarts.init(_dom, 'ascm');
      this.chartInstance.setOption(this.eoption);
      this.firstInit = false;
      this.eloading = false;
    });
}

ng2-ChangeDetectionStrategy提升性能

吴阳 No Comments

import { Component, OnInit, ViewEncapsulation, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core';

@Component({
  selector: 'scm-side-menu',
  templateUrl: './side-menu.component.html',
  styleUrls: ['./side-menu.component.scss'],
  encapsulation: ViewEncapsulation.None, // 增加该元数据则会让该组件的样式应用到整个app
  changeDetection: ChangeDetectionStrategy.OnPush
})

constructor(
  private cd:ChangeDetectorRef) { }

public data = []; // 此data已在页面绑定html
public clickBtn(item){
  this.data.push(item);
  this.data = JSON.parse(JSON.stringify(this.data)); // clone数组
  this.cd.detectChanges(); // 在需要更新视图时手动触发ng的检测
}

利用这个机制可以提高性能。避免ng去全部检测(ng2默认是会去检测所有的页面节点)。

ng2-EventEmitter

吴阳 No Comments

demo:

1.组件样式问题

A组件嵌入了B组件,那么被嵌入的结构的样式应写在B组件内。

2.组件通讯

父组件中,对子组件进行事件绑定:
html

<app-loader [url]="'/api/index/index'" [method]="'get'" [body]="body" (onReceive)="receiveTheData($event)"></app-loader>

ts

export class FindComponent implements OnInit {
  receiveTheData(action) {
    // 从loader组件返回action
    // console.log(action);
    this.topCarousel = action.locationAds[0].ads;
    this.list = action.hotProducts;
  }
}

子组件输出
ts

export class LoaderComponent implements OnInit, OnChanges {
data;
@Output() onReceive = new EventEmitter();
  receiveTheData() {
    this.onReceive.emit(this.data);
  }
  ngOnInit(){
   this.ajax(){

   //假如异步返回是res的结果

   this.data = res;
   this.receiveTheData();
   }
 }
}

3.对于angular HTML中,各标签属性的应用。
模板绑定是通过 property 和事件来工作的,而不是 attribute。
在 Angular 的世界中,attribute 唯一的作用是用来初始化元素和指令的状态。 当进行数据绑定时,只是在与元素和指令的 property 和事件打交道,而 attribute 就完全靠边站了。

举个例子:
data = '<p>123</p>'
<div [innerHTML]="data"></div>
输出:
<div>
<p>123</p>
</div>