javascript - RangeError:Angular 中超出了最大调用堆栈大小
问题描述
我的 Angular 应用程序类型的 stackOverflow 出现错误。(见最后更新)
基本上我的组件是一个包含两个组件的图表。equipment
包含设备信息的组件和socket
组件,包括每个设备的连接类型。套接字组件基本上显示了一个下拉列表,其中包含可连接的设备。“容器”组件基本上创建了一个类型为“开始元素”的套接字组件,因此我们有一个“假”连接来选择一个开始元素。从那时起,我们选择一个起始元素,我们可以继续输入图表。当我选择第一个“开始元素”(pic1)时,相应的设备将加载其相应的插座(7 个单元)。然后我在其中一个插座上选择了一个设备(pic2),同样,它装载了一个单元,一切都很好。然后我在相应的套接字(pic3)中再选择一个设备,然后,应用程序崩溃了。
我收到此错误:
ERROR RangeError: Maximum call stack size exceeded
at refreshView (core.js:9461)
at refreshEmbeddedViews (core.js:10591)
at refreshView (core.js:9490)
at refreshComponent (core.js:10637)
at refreshChildComponents (core.js:9263)
at refreshView (core.js:9516)
at refreshEmbeddedViews (core.js:10591)
at refreshView (core.js:9490)
at refreshComponent (core.js:10637)
at refreshChildComponents (core.js:9263)
我制作了一些控制台日志,在发生错误的单击处,第一个开始元素被呈现(ngOnInit),第二个也是如此,在我单击的第三个中,Socket onInit 和 Equipment onInit 被无止境地调用。所以似乎设备和套接字都在无休止地调用自己。
我检查了我的应用程序,我只调用了两次套接字组件。一旦在容器组件上创建“开始元素”套接字,然后在设备组件上的 ngfor 上。而关于设备,它在整个应用程序中只被调用一次,mySocket.element
被选中一次并且不为空,因此 ngIf 显示了组件。
我只有一个模块app.module
,所以这里相同,没有对组件的多次调用。
这里是socket组件:
import { Component, Input, OnInit } from '@angular/core';
import { Equipment } from 'src/app/model/Equipment';
import { Socket } from 'src/app/model/Socket';
import { EquipmentService } from 'src/app/services/equipment.service';
@Component({
selector: 'app-socket',
templateUrl: './socket.component.html',
styleUrls: ['./socket.component.css']
})
export class SocketComponent implements OnInit {
@Input() mySocket: Socket;
@Input() parentEquipment: Equipment;
myElements: Equipment[];
constructor( private _equipmentNewService:EquipmentService) { }
ngOnInit(): void {
console.log("Myparentequipment:", this.parentEquipment)
this.myElements = this._equipmentNewService.getListForGivenInput(this.mySocket.type);
}
loadEquipment(eq:Equipment){
this.mySocket.element = eq;
}
amIFirstConnection(){
return !this.amIOnlyConnection() && this.mySocket === this.parentEquipment.eqType.connections[0];
}
amILastConnection(){
return !this.amIOnlyConnection() && this.mySocket === this.parentEquipment.eqType.connections[this.parentEquipment.eqType.connections.length-1];
}
amIMiddleConnection(){
return !this.amIOnlyConnection() && !this.amIFirstConnection() && !this.amILastConnection();
}
amIOnlyConnection(){
return this.parentEquipment.eqType.connections.length===1
}
}
这里的html文件:
<!-- this is just to create the diagram lines, ignore it! -->
<div *ngIf="mySocket.type !== 'Start Element'">
<div *ngIf="amIOnlyConnection()" class="d-flex someMarginTop">
<div class="smallSpacer schema"></div>
<div class="mainSpacer schema borderLeft"></div>
</div>
<div *ngIf="amIFirstConnection()" class="d-flex someMarginTop">
<div class="smallSpacer schema"></div>
<div class="mainSpacer schema borderLeft borderTop"></div>
</div>
<div *ngIf="amIMiddleConnection()" class="d-flex someMarginTop">
<div class="smallSpacer schema borderTop"></div>
<div class="mainSpacer schema borderTop borderLeft"></div>
</div>
<div *ngIf="amILastConnection()" class="d-flex someMarginTop">
<div class="smallSpacer schema borderTop"></div>
<div class="mainSpacer schema borderLeft"></div>
</div>
</div>
<!-- here we display the info -->
<div class="dropdown someMargin">
<button class="btn btn-outline-secondary btn-sm dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
{{mySocket.name}}...
</button>
<ul class="dropdown-menu listSocket" aria-labelledby="dropdownMenuButton1">
<li *ngFor="let item of myElements">
<div class="d-flex"><a class="dropdown-item" (click)="loadEquipment(item)"><span style="margin-right:5px">{{item.eqType.productNumber}}</span></a></div>
</li>
</ul>
<!-- and here the call to equipment -->
<div *ngIf="mySocket.element">
<app-equipment [equipment]="mySocket.element" [parentSocket]="this.mySocket"></app-equipment>
</div>
</div>
现在是设备组件:
import { Component, Input, OnInit } from '@angular/core';
import { Equipment } from 'src/app/model/Equipment';
import { Socket } from 'src/app/model/Socket';
@Component({
selector: 'app-equipment',
templateUrl: './equipment.component.html',
styleUrls: ['./equipment.component.css']
})
export class EquipmentComponent implements OnInit {
@Input() equipment: Equipment;
@Input() parentSocket: Socket;
constructor() {
}
ngOnInit(): void {
console.log("Myparentsocket:", this.parentSocket)
this.equipment.available = false;
}
removeMyselfFromSocket() {
this.parentSocket.element = null;
}
}
这里的html文件:
<div class="someMargin somePadding col-md-auto border rounded eqContainer animated fadeIn fast">
<div style="float:right">
<button type="button" class="btn btn-outline-danger px-3" style="padding: 0px 7px !important;" (click)="removeMyselfFromSocket()"><i class="fas fa-trash fa-xs"></i></button>
</div>
<div class="d-flex">
<div>
<!-- <img [src]="equipment.eqType.img" class="img-fluid imgTestModel" [alt]="equipment.eqType.productNumber"> -->
</div>
<div style="margin-left:5px" class="bg-light border rounded somePadding" style="margin-right:30px">
<!-- <p class="title p-lessMargin text-primary">{{equipment.eqType.productNumber}}</p> -->
<p class="ids p-lessMargin">ProductNO: <span class="ids-content">ABC8493RT</span> </p>
<p class="ids p-lessMargin">SerialNO: <span class="ids-content">15698247896</span></p>
<p class="ids p-lessMargin">SwRev: <span class="ids-content">2.2.145</span></p>
</div>
</div>
<div class="d-flex">
<app-socket *ngFor="let socket of equipment.eqType.connections" [mySocket]="socket" [parentEquipment]="equipment"></app-socket>
</div>
</div>
我希望我附上了足够的信息,我很乐意得到一些帮助!
提前致谢 :)
更新 1: 在套接字组件上更改此方法后(以避免始终调用更改检测器):
equipmentSelected:Equipment;
loadEquipment(eq:Equipment){
this.equipmentSelected = eq;
}
我现在可以将更多孩子添加到我的树中。现在的问题是,我该怎么做才能保持this.mySocket.element = eq
?否则我会丢失我的树结构并且无法序列化我的对象......
解决方案
在一位好朋友的帮助下,我找到了解决方案。它loadEquipment()
位于套接字组件上的方法上。当它更改在此组件上创建的对象 mySocket 时,该组件被再次渲染,并且由于它是来自父套接字的输入,父套接字设备组件也被再次渲染,从而在加载相互引用的组件时创建堆栈溢出整个时间。
我需要将方法更改为:
loadEquipment(eq:Equipment){
// js workaround for cloning
this.mySocket.element = JSON.parse(JSON.stringify(eq));
}
创建对象的克隆可以让更改检测器保持安静并避免重新渲染。
推荐阅读
- python - 在python中拆分键值字符串并将其移动到df列中
- python - 任何人都可以解释列表中 is 运算符的工作机制吗?
- visual-studio - 当我在手机中安装我的 apk 时,它显示“您要安装此应用程序吗?它不需要任何特殊访问权限。”
- javascript - mongoose -schema 选项针对特定字段更新
- centos7 - 执行openstack的剧本时无法连接到我的sql
- php - 登录到 myPhpAdmin
- python - Python。将新数字覆盖到矩阵的列中
- ibm-watson - 如何从 Watson 中删除服务?
- php - 带有php邮件发送的联系表
- hive - 如何抑制蜂巢警告