首页 > 解决方案 > 更改界面中的数据后的角度html更新

问题描述

我想做的是更新我的界面,它有一些用户信息,然后当它发生变化时,我希望结果反映在 HTML 输出中。

在我的 HTML 页面上,我有一个输入,允许用户添加附加评论。这一切正常,但是,用户输入实际上并未显示在页面上,但确实对我的界面进行了必要的更改。

在下面的 HTML 文件中,用户将在输入中键入一些内容。然后将保存到我的界面,这是每个学生的数据,然后将在此处可见<p>{{the students.grades}}<p>

<div class='studentCard' *ngFor='let student of students | studentSearch: StudentSearch'>
            <img class='studentImg' src={{student.pic}}/>
            <div class='studentInfo'>
                <h1>{{student.name | uppercase}}</h1>
                <div class='loca'>
                    <p>Email: <span>{{student.email}}</span></p>
                    <p>Company: <span>{{student.company}}</span></p>
                    <p>Skill: <span>{{student.skills}}</span></p>
                    <p>Average: <span>{{student.average}}</span></p>
                    <mat-expansion-panel [hideToggle]='true' [expanded]='true'>
                            <p>{{student.grades}}</p>
                    </mat-expansion-panel>
                    <p>{{student.tags}}</p>
                    <mat-form-field>
                    <input  matInput (keyup.enter)='add(student.id)' placeholder="Add a tag"></mat-form-field>
                </div>
            </div>
            <div class='expand'><span class='material-icons'>add</span></div>
        </div>

此代码来自我的 component.ts 文件。现在我只是想传递一些虚拟信息来看看它是否真的有效。我可以看到它正确地更新了界面。

import { Component, OnInit } from '@angular/core';
import { Student } from '../student'
import { StudentsService } from '../students.service';

@Component({
  selector: 'app-student-profiles',
  templateUrl: './student-profiles.component.html',
  styleUrls: ['./student-profiles.component.scss']
})
export class StudentProfilesComponent implements OnInit {
  //implementing an interface to control the data and make it easy to access
  students: Student[] = [];
  StudentSearch=''
  TagSearch=''

  constructor(
    private service: StudentsService
  ) { }

  ngOnInit(): void {
    this.service.getStudents().subscribe(
      result=>result['students'].map(
        x=>{this.students.push(
          {
            name:x.firstName+' '+x.lastName,
            grades:x.grades,
            average:this.computeAvg(x.grades),
            company: x.company,
            email: x.email,
            pic: x.pic,
            id: x.id,
            skills: x.skill,
            tags:[]
          }); 
          }
        )
    )
  }
  //find the average of all the scores of each student.  Calculates the total, then devides by the length of scores array.
  computeAvg(x){
    let total=0
    x.map(score=>{total=total+Number(score)})
    return(total/x.length)

  }
  add(id){
    this.students[id-1]['tags'].push(String('100'))
    console.log(this.students[id-1])
  }

}

这是我用于数据的接口:

    name: string;
    grades: number[];
    average: number;
    company: string;
    pic: string;
    email: string;
    id: number;
    skills: string;
    tags: string[];
    

}

我不明白的是,如果我使用相同的代码,但我将它从“标签”更改为“电子邮件”,那么它确实会在 HTML 中显示更新。

标签: angulartypescript

解决方案


Angular Change Detection 通过比较模板中存在的属性的新旧值来工作。

如果您仔细观察您的界面,email 属性是一个字符串,但 tags 属性是一个数组。

当您更改电子邮件的值时,Angular 能够知道此原始类型的新旧值不同,然后更新视图。

当您向 tags 数组添加新标签时,对数组的引用不会更改它只会更改其内容,因此 Angular 不会检测到它,因此不会更新视图。

在这种情况下,一个非常简单的解决方案是在添加新标签后创建一个新数组,以便引用更改,您可以使用拼接或展开运算符来做到这一点:

array.slice()
or
[...array]

考虑到您正在制作数组的副本。

当引用未更改并且需要副本时,角度更改检测的相同行为适用于对象类型。

其他一些 Web 框架(即 React)使用不可变范式使这些事情更容易理解并避免陷阱。

有关角度变化检测的更多信息:

https://dzone.com/articles/how-to-use-change-detection-in-angular#:~:text=Change%20Detection%20means%20updating%20the,detector%20to%20update%20the%20DOM


推荐阅读