【问题标题】:How to work with change detection strategy on-push in angular for array如何使用变化检测策略 on-push in angular for array
【发布时间】:2020-09-29 17:09:25
【问题描述】:

在这里,我试图研究变更检测的工作原理。使用更改检测OnPush 在父组件和子组件中具有数组(子项)。试图通过拼接或推送来改变数组,仍然影响子组件模板。即使@Input 的引用没有改变,这怎么行?

我的父组件.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, AfterViewInit {
  children = [1,2,3,4,5,6,7,8,9]

  emit(j) {
    this.children.splice(j, 1);
  }
}

父级html

<div>
   <app-multi [input]="children" (output)="emit($event)"></app-multi>
</div>

我的子组件.ts

@Component({
  selector: 'app-multi',
  templateUrl: './multi.component.html',
  styleUrls: ['./multi.component.css'],
  changeDetection:ChangeDetectionStrategy.OnPush
})
export class MultiComponent implements OnInit,OnChanges,DoCheck,AfterViewInit{

  @Input('input') ele = [];

  data = [];

  @Output('output') outputEmi = new EventEmitter();

  ngOnInit() {
    this.data = this.ele;
  }

  clicks(value){
    this.outputEmi.emit(value);
  }

}

子html

{{name.name}}
<table>
    <tbody>
        <tr>
            <td *ngFor="let head of data; let i = index;">
                <span>{{head}}</span>
                <button class="delete" (click)="clicks(i)">x</button>
            </td>
        </tr>
    </tbody>
</table>

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    为了触发更改检测,当它是 OnPush 时,您必须更改引用,所以如果您使用 splice 它不会更改引用,它只会更新现有数组,所以我鼓励您使用 filter 方法而不是splice,但如果你必须使用拼接而不是记得像这样更新引用

    this.children.splice(i,j);
    this.children = [...this.children]
    

    【讨论】:

      【解决方案2】:

      据我了解,您的问题是您想知道为什么更改检测有效,即使 @Input 的引用没有改变?

      将更改检测策略设置为OnPush,子组件检查其模板绑定仅出于以下几个原因:

      • @Input() 值的原语或引用已更改
      • 发生了绑定事件,该事件在模板内声明(如 (click))
      • 子组件通过@Output发出

      在您的情况下,第二点也是最后一点发生了,因此您的子模板中的*ngFor 再次运行,并意识到输入中的数组有一个额外的添加。

      底线,因此即使数组的引用保持不变,并且@Input() 没有明智地更改引用,仍然会触发更改检测,因为子组件接收到绑定的(click) 并发出一个@Output.

      如果您要更新代码,而不使用 @Output(),则更改检测仍然有效,因为事件已绑定到模板:

      clicks(value){
        this.input.splice(value, 1);
      }
      

      【讨论】:

      • 谢谢兄弟,这对我有很大帮助,你能解释一下markForCheck的使用吗
      • 角度变化检测是从根部到底部进行的。这意味着如果父组件具有OnPush,则无论其设置如何,子组件也将表现为OnPush。想象一下所有组件都是OnPush。如果您从子级调用markForCheck,它将冒泡到根,将所有祖先标记为“脏”,这意味着在下一个tick()(更改检测)中,组件将得到更新。 (虽然不是孩子的孩子)。这与detectChanges 有点相反,因为它会从一个孩子传到另一个孩子,并且只会更新脏的。
      猜你喜欢
      • 1970-01-01
      • 2018-05-03
      • 1970-01-01
      • 2019-08-20
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      • 1970-01-01
      相关资源
      最近更新 更多