因此,我的应用程序组件中有一个div集合,其中填充了app-cube
个组件,父组件中的数组中包含了GridProp
个对象,它们的索引表示集合中的每个单元格,意思是我根据array [i]的内容创建每个“单元格”的内容。
在array [i]中,我有一个带有Observable的对象,例如单元格的内容。 当我更新单元格i
中的内容时,我想更新单元格[i-1]
和[i+1]
的兄弟姐妹。
我试图通过让每个app-cube
订阅数组中匹配对象中的observable来做到这一点。这样,我应该能够简单地将值发送到数组中任何索引处的观察者,并使其触发已订阅组件的订阅处理程序,对吧?
数组中的对象属于此类
export class GridProp implements OnInit {
private terrain = new Terrain();
coord: Array<number>;
cont: {};
observer: Observer<string>;
observable: Observable<string> = new Observable((observer: Observer<string>) => {
this.observer = observer;
});
}
然后在cube-component.ts中
@Component({
selector: 'app-cube',
templateUrl: './cube.component.html',
styleUrls: ['./cube.component.css']
})
export class CubeComponent implements OnInit {
@Input() point; // Represents the relevant GridProp object
ngOnInit() {
this.point.observable.subscribe(this.handleCubeUpdate);
}
handleCubeUpdate() {
console.log('handling!');
this.updateWalls();
}
updateWalls() {
// Do stuff to the "walls" values used in this cube.component.html
}
toggleWalls() {
for (const direction in this.point.cont.terrain.walls) {
if (this.getSide(direction) && this.getSide(direction).cont.terrain.isBlock) {
this.point.cont.terrain.walls[direction] = false;
this.getSide(direction).observer.next(true);
} else {
this.point.cont.terrain.walls[direction] = true;
}
}
this.updateWalls();
}
}
在父组件中,我分散了应用程序多维数据集
<div class="grid-point-z" *ngFor="let z of y">
<div
class="grid-point"
attr.data-point="{{ z.coord }}"
[ngStyle]="{
'z-index': z.coord[2]
}">
<app-cube
[point]="z"
[coord]="z"
[level]="level"
(click)="clickPoint(z)"
(change)="onCubeChange($event)">
{{z}}
</app-cube>
</div>
</div>
它因错误而崩溃
ERROR TypeError: this.updateWalls is not a function
at SafeSubscriber.push../src/app/assets/cube/cube.component.ts.CubeComponent.handleCubeUpdate [as _next] (cube.component.ts:71)
因此,我想它在CubeComponent的订阅中无法识别this.handleCubeUpdate
。有解决方法吗?
答案 0 :(得分:2)
现在,对我而言,我可以在这里尝试回答这个问题更有意义。
希望我能正确表达this
:)。
因此,当您在subscribe
中传递函数引用时,this
中的handleCubeUpdate
具有不同的上下文。
您可以将函数实现更改为箭头函数。
handleCubeUpdate = () => {
this.updateWalls();
}
另外,如果您的updateWalls
正在调用另一个函数,则应更改该updateWalls
函数箭头功能。
答案 1 :(得分:1)
从我的角度来看,我们遇到了一些设计问题。
在Angular中,组件可以使用它们的@Input()
和@Output()
属性进行交互(输入-要了解父组件和更新视图的更改,输出-要通知其他人内部的更改)
最好将其添加到CubeComponent
输出事件somethingChanged
中,并在您更新内容时发出此事件。
export class CubeComponent implements OnInit {
@Input() point; // Represents the relevant GridProp object
@Output() somethingChanged = new EventEmitter<GridProp>();
ngOnInit() {
}
notifyOthersComponentAboutUpdate() {
let id = this.point; // You can emit point or some id, to identify it later in parent component
this.somethingChanged.emit(id);
}
}
在包含app-component
个组件数组的父组件(app-cube
)中,创建方法updateSiblings(idOfComponentWhichWasUpdated)
并从app-cube
组件中调用它
<div class="grid-point-z" *ngFor="let z of y">
<div
class="grid-point"
attr.data-point="{{ z.coord }}"
[ngStyle]="{
'z-index': z.coord[2]
}">
<app-cube
[point]="z"
[coord]="z"
[level]="level"
(somethingChanged)="updateSiblings($event)">
{{z}}
</app-cube>
</div>
</div>
在该updateSiblings
方法中,您可以访问y
数组(*ngFor="let z of y"
),其中包含app-cube
个组件(y: GridProp[]
)的所有数据。 br />
您具有已更新的组件ID,因此可以在数组y
中找到它,还可以找到其兄弟姐妹并更新其数据。 Angular将自动检测该y
数组中的更改,并且您的兄弟姐妹将在UI级别进行更新。
答案 2 :(得分:0)
您是否考虑过在Angular中使用REDUX架构?
Here's a good tutorial了解其运作方式和优势。我使用了完全相同的教程来学习和实现。
然后,您可以将该阵列保留在商店中,并调度操作以更改事物。每个动作都可能包含更新自身的逻辑及其周围的两个项目。