Angular5 模板绑定,多次调用回调函数 [英] Angular5 template binding, callback function called more than once

查看:33
本文介绍了Angular5 模板绑定,多次调用回调函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用包含列定义及其数据数组的结构化数据实现网格组件.

在每一列的定义中有一个callback函数,用于自定义显示该列的值.

在每个callback内部,它调用了一个console.log()来显示回调函数将被调用多少次.

我不知道为什么回调函数一开始调用了四次,而在changeSort() 事件触发后又调用了两次!!请告诉我.

我编写了以下表格组件:

import { Component, OnInit, Input } from '@angular/core';@成分({选择器:'应用程序表',templateUrl: './table.component.html',styleUrls: ['./table.component.css']})导出类 TableComponent 实现 OnInit {//@Input() 公共网格:{//列:任何[],//数据:任何[]//};公共电网:任何;构造函数(){this.grid = {列: [],数据: [],};}ngOnInit() {this.grid = {数据: [{desc: '你好 1',标题:'我的标题1'},{desc: '你好 2',标题:'我的标题2'},{desc: '你好 3',标题:'我的标题3'}],列: [{标题描述',字段:'desc',可排序:假,回调:(值)=>this.myCallback1(value),},{title: '标题',字段:'标题',可排序:真实,回调:(值)=>this.myCallback2(value),},],};}公共更改排序(字段){控制台日志(字段);}公共 myCallback1(value) {console.log('myCallback', value);返回值 + 'mc1';}公共 myCallback2(值){console.log('myCallback2', value);返回值 + 'mc2';}}

它的模板是这样的:

<table class="table table-striped table-sm"><头><tr><th>#</th><th *ngFor="let col of grid.columns"><span (click)="changeSort(col)" *ngIf="col.sortable">{{col.title}}</span><span *ngIf="!col.sortable">{{col.title}}</span></th></tr></thead><tr *ngFor="let row of grid.data; let i = index"><td>{{i+1}}</td><td *ngFor="let col of grid.columns">{{col.callback ?col.callback(row[col.field]) : row[col.field]}}</td></tr></tbody>

这里是开头的日志错误:

myCallback hello 1myCallback2 我的标题 1我的回调你好 2myCallback2 我的标题 2我的回调你好 3myCallback2 我的标题 3我的回调你好 1myCallback2 我的标题 1我的回调你好 2myCallback2 我的标题 2我的回调你好 3myCallback2 我的标题 3我的回调你好 1myCallback2 我的标题 1我的回调你好 2myCallback2 我的标题 2我的回调你好 3myCallback2 我的标题 3我的回调你好 1myCallback2 我的标题 1我的回调你好 2myCallback2 我的标题 2我的回调你好 3myCallback2 我的标题 3

解决方案

Angular 处理模型和 dom(组件和模板文件)之间的绑定.为此,应用程序会滴答(更改检测周期)并检查是否有任何值发生了更改,如果是,则 -> 更新 dom.

问题是当您的模板文件中有函数时,每个循环角度都会调用该函数以检查值"是否已更改.

例如,如果我有一个简单的 get 函数,它只返回一个值,Angular 需要运行它来检查是否确实发生了变化.

{{ myValue() }}//在模板文件中myValue() { return 10 }//在组件中

这里有道理,angular 必须调用每个函数来检查值是否已更改.

一个解决方案(如果您不希望 Angular 不断调用您的函数),是实现 ChangeDectionStrategy (https://angular.io/api/core/ChangeDetectionStrategy).有了这个,您可以告诉 Angular 您将处理更新,以及它应该何时运行循环(仅针对该组件).

要在组件元数据中执行此操作,您将添加以下内容:

@Component({选择器:'应用程序表',templateUrl: './table.component.html',styleUrls: ['./table.component.css'],changeDetection: ChangeDetectionStrategy.OnPush//新行})

然后在构造函数中:

constructor(private changeDetectorRef: ChangeDetectorRef) {}

每当您进行更改时,您都可以调用 this.changeDetectorRef.markForCheck(); 这将手动运行此组件的循环并在需要时更新 dom.

我真的建议多阅读这个话题,因为这个话题太广泛了,无法在这篇文章中描述

I tried to implement a grid component with a structured data containing columns definition and its data array.

There is a callback function in the definition of each column, to customize displaying the value of that column.

Inside of each callback, it called a console.log() to show me how many times the callback function will be called.

I don't know why callback function called four times in the beginning, and two times after changeSort() event fired !! Please let me know.

I wrote the following table component:

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

@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {

  // @Input() public grid: {
  //   columns: any[],
  //   data: any[]
  // };

  public grid: any;

  constructor() {
    this.grid = {
      columns: [],
      data: [],
    };
  }

  ngOnInit() {
    this.grid = {
      data: [
        {
          desc: 'hello 1',
          header: 'my header 1'
        },
        {
          desc: 'hello 2',
          header: 'my header 2'
        },
        {
          desc: 'hello 3',
          header: 'my header 3'
        }
      ],
      columns: [
        {
          title: 'Description',
          field: 'desc',
          sortable: false,
          callback: (value) => this.myCallback1(value),
        },
        {
          title: 'Header',
          field: 'header',
          sortable: true,
          callback: (value) => this.myCallback2(value),
        },
      ],
    };
  }

  public changeSort(field) {
    console.log(field);
  }

  public myCallback1(value) {
    console.log('myCallback', value);
    return value + ' mc1';
  }

  public myCallback2(value) {
    console.log('myCallback2', value);
    return value + ' mc2';
  }

}

And its template is this :

<div class="table-responsive">
  <table class="table table-striped table-sm">
    <thead>
    <tr>
      <th>#</th>
      <th *ngFor="let col of grid.columns">
        <span (click)="changeSort(col)" *ngIf="col.sortable">{{col.title}}</span>
        <span *ngIf="!col.sortable">{{col.title}}</span>
      </th>
    </tr>
    </thead>
    <tbody>
    <tr *ngFor="let row of grid.data; let i = index">
      <td>{{i+1}}</td>
      <td *ngFor="let col of grid.columns">{{col.callback ? col.callback(row[col.field]) : row[col.field]}}</td>
    </tr>
    </tbody>
  </table>
</div>

Here is log error at the beginning :

myCallback hello 1
myCallback2 my header 1
myCallback hello 2
myCallback2 my header 2
myCallback hello 3
myCallback2 my header 3
myCallback hello 1
myCallback2 my header 1
myCallback hello 2
myCallback2 my header 2
myCallback hello 3
myCallback2 my header 3
myCallback hello 1
myCallback2 my header 1
myCallback hello 2
myCallback2 my header 2
myCallback hello 3
myCallback2 my header 3
myCallback hello 1
myCallback2 my header 1
myCallback hello 2
myCallback2 my header 2
myCallback hello 3
myCallback2 my header 3

解决方案

Angular handles the binding between the model and the dom (component and template file). To do this the application ticks (change detection cycle) and checks for if any values that have changed, and if so -> Update the dom.

The problem is when you have functions in your template file, and each cycle angular will call the function to check if the 'value' has changed.

For example, if I had a simple get function which only returned a value, Angular needs to run it to check that there is actually a change.

{{ myValue() }} // in the template file

myValue() { return 10 } // in the component

Here it makes sense that angular must call the function each to check if the value has changed.

A solution (if you don't want Angular to be constantly calling your functions), is to implement a ChangeDectionStrategy (https://angular.io/api/core/ChangeDetectionStrategy). With this, you can tell Angular that you will handle the updates, and when it should run the cycle (for only that component).

To do so within the component metadata you will add the following:

@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css'],
  changeDetection: ChangeDetectionStrategy.OnPush // the new line
})

Then in the constructor:

constructor(private changeDetectorRef: ChangeDetectorRef) {}

Whenever you make a change, you can then call this.changeDetectorRef.markForCheck(); which will manually run the cycle for this component and update the dom when needed.

I really suggest reading into this more as the topic is too broad to describe in this one post

这篇关于Angular5 模板绑定,多次调用回调函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆