【问题标题】:How to detect change of complex object in Angular?如何检测Angular中复杂对象的变化?
【发布时间】:2019-08-28 14:54:47
【问题描述】:

我正在做一个有角度的项目。所以我有一个复杂的样式对象,我将它绑定到我的角度组件。

app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

    style:any;

    ngOnInit() {
        this.style = { 
            radius:15, 
            fill: { 
                color: "red" 
            }, 
            stroke: { 
                color: "blue", 
                width: 3 
            } 
        }
    }
}

app.component.html

my-component 获取对象并将其与第三方对象一起使用。

my.component.ts

@Component({
    selector: 'my-component',
    template: `<ng-content></ng-content>`,
})
export class MyComponent implements AfterContentInit {
    style: any;
    thirdPartyObject: Style;

    ngOnInit(): void {
        this.style = new Style({
            radius: style.radius,
            fill: new Fill({ color: style.fill.color }),
            stroke: new Stroke({ color: style.stroke.color, width: style.stroke.width })
        });
    }

    ngAfterContentInit(): void {
        thirdPartyObject.setStyle(function(){
            return this style;          
        })
    }
}

我正在使用来自 app.component 的样式对象创建第三方样式对象。而thirdPartyObject 有一个名为setStyle() 的函数来获取样式对象。

那么当我在 app.component 中更改 style 的属性时,如何更新 my-component 呢?这个绑定是不同的。

【问题讨论】:

  • 你可以使用EventEmitter。
  • how can I refresh the my-component ,您需要在MyComponent..中更新什么?
  • @ganesh045 角度属性绑定触发子组件。当我更改属性绑定的子组件时,它会立即更改。但在这种情况下,我有一个复杂的对象。那么我该怎么做呢?
  • this stuation I have a complex object 这与复杂对象或简单对象无关。您需要更新什么,是来自父组件的子组件变量还是来自子组件的父组件变量...?可能是我无法正确理解您的要求。你能详细说明一下吗... ;)

标签: angular angular7 angular8


【解决方案1】:

您可以使用 Angular 的 ChangeDetectorRef 手动检测更改并触发渲染

@Component({
    selector: 'my-component',
    template: `<ng-content></ng-content>`,
})
export class MyComponent implements AfterContentInit {
    style: any;
    thirdPartyObject: Style;

    constructor(private ref: ChangeDetectorRef) { }

    ngOnInit(): void {
        this.style = new Style({
            radius: style.radius,
            fill: new Fill({ color: style.fill.color }),
            stroke: new Stroke({ color: style.stroke.color, width: style.stroke.width })
        });
    }

    ngAfterContentInit(): void {
        this.setStylesToThirdPartyObject();
    }

    setStylesToThirdPartyObject(): void {
        thirdPartyObject.setStyle(function(){
            return this style;          
        });
        this.ref.detectChanges();
    }
}

https://angular.io/api/core/ChangeDetectorRef上阅读有关 CDR 的更多信息

【讨论】:

    【解决方案2】:

    这是一个角度变化检测的完整示例:

    import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
    import { CalcComponent } from '../calc-component';
    
    @Component({
      selector: 'app-circular-area',
      templateUrl: './circular-area.component.html',
      styleUrls: ['./circular-area.component.scss']
    })
    export class CircularAreaComponent implements OnInit {
      public render: Boolean;
      public radius: number;
      public r: number;
      constructor(private cdRef: ChangeDetectorRef) { }
    
      **onChange**(event: any, r: number) {
        console.log(r);
        this.r = Number(r);
        this.render = true;
        this.cdRef.detectChanges();
        this.render = false;
      }
    
      ngOnInit() {
        this.render = false;
      }
    }
    

    <div class="mat-elevation-z8">
        <form  **(change)="onChange($event,r.value)**">  
            <fieldset class="material">
              <label>Radius</label>
              <hr>
              <input #r type="number" placeholder={{radius}} autocomplete="on" value = 5 required> 
            </fieldset>
            <ng-container *ngIf="!render">
               <app-calc-component value={{r.value}} selCalc='circulararea'></app-calc-component>
          </ng-container>
          </form>
     </div>
    

    onChange 方法触发 changeDetection。另请参阅我的 git 中的计算组件

    【讨论】:

      【解决方案3】:

      我建议使用 @Input 类装饰器将样式传递给您的子组件,因此 Angular 可以跟踪 style 对象并重新渲染您的孩子检测到变化时的组件。

      在您的 app.component.html 中:

      <your-component [style]="style"></your-component>
      

      在您的子组件 ts 文件中,在 ngOnInitngOnChanges 中应用 setStyle

       @Input() style: any;
       ngOnInit() {
         thirdPartyObject.setStyle(function() { return this.style });
       }
       ngOnChanges() {
         thirdPartyObject.setStyle(function() { return this.style });   
       } 
      

      并且由于 style 是一个对象,角度跟踪它是参考,而不是它的属性,所以你必须通过创建新对象来更改 style(类似于改变反应的状态):

      在您的应用组件 ts 文件中:

      changeStyleStroke(){
         let newStroke = {
            stroke: { 
              color: "red", 
              width: 3 
            } 
         };
      
         //Update style this way will trigger change detection that detect changes and re-render your component
      
         this.style = {...this.style, ...stroke};
       }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-05
        • 1970-01-01
        • 1970-01-01
        • 2016-04-21
        相关资源
        最近更新 更多