如何与另一个组件共享对组件二维数组的引用?
How to share a reference to a component's 2d array with another component?
我正在尝试在 Angular 中构建一个生命游戏应用程序。我有一个 grid
组件用于显示生命游戏网格,每个单元格要么死要么活(它本身没有任何生命游戏逻辑,只显示一个可点击的单元格网格)。 grid
组件有一个 2d gameplane: bool[][]
数组来表示 Game of Life 网格;每个单元格的信息都存储在该二维数组中。 grid component
还有一个 width: number
和一个 height: number
属性 来确定网格的尺寸。这两个都有一个 setter 根据传递的值调整 gameplane
的大小。
现在我想以某种方式 "share" 这 3 个属性与另一个不相关的组件 (control-panel
),这是通过服务完成的(但我不知道如何)。生命游戏逻辑不应在 grid
组件中。
我现在的问题是我需要能够读取和设置服务中的 3 个属性中的每一个,因为这是我计划放置逻辑的地方;例如,我需要能够读取组件的 gameplane
属性 以查看用户如何设置单元格的状态,这发生在 grid
组件本身,我还需要写入 gameplane
属性 以根据生命游戏的规则为下一个循环设置每个单元格的状态。
我尝试过使用 rxjs,但并没有真正理解我在做什么,这并没有给我想要的结果。这是一些代码:
grid.component.ts
// ... imports ...
@Component({
selector: "app-grid",
templateUrl: "./grid.component.html",
styleUrls: ["./grid.component.scss"]
})
export class GridComponent implements OnInit {
mousedown: boolean;
gameplane: boolean[][];
isMousedown: boolean = false;
private _width: number;
private _height: number;
// logic for click and mouseenter events...
grid.component.html(与问题无关)
<div>
<table
(mousedown)="isMousedown = true"
(mouseup)="isMousedown = false"
(mouseleave)="isMousedown = false"
>
<tr *ngFor="let row of gameplane; index as yCoord">
<td *ngFor="let cell of row; index as xCoord; trackBy:trackByTd"
(mousedown)="gameplane[yCoord][xCoord] = !gameplane[yCoord][xCoord]"
(mouseenter)="invertCellOnMouseEnter(yCoord, xCoord)"
class="cell"
>
</td>
</tr>
</table>
</div>
game-control.service.ts(我需要的一些功能)
@Injectable({
providedIn: 'root'
})
export class GameControlService {
evolveInterval: 1000;
isEvolving: boolean = false;
fillGameplane(state: boolean) {
// Fills each cell in the gameplane-array in grid.component with 'state' values.
}
randomizePlane() {
// Randomly fills each cell in the gameplane-array in grid.component with either true or false.
}
evolvePlane(){
// Reads the current value of the gameplane-array in grid.component and sets each cell's state
// depending on the state of the cell's neighbours according to the rules of the Game of Life
changeWidth(){
// Changes the width-poperty in grid.component
}
constructor() {}
}
- 既然你想在两个不相关的组件之间共享数据,你应该使用数据服务。本文非常详细地讨论了您应该如何操作(视频 + 代码示例)https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
changeMessage(message: string) {
this.messageSource.next(message)
}
}
-------------------------------------------
@Component({
selector: 'component1'
})
export class ParentComponent implements OnInit {
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(data => console.log(data))
}
}
-------------------------------------------
@Component({
selector: 'component2'
})
export class SiblingComponent implements OnInit {
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(data => console.log(data))
this.data.changeMessage("Update the data")
}
}
注意:如果要共享大量复杂的数据,应该考虑使用redux,或者ngrx。这将需要一些学习。 https://medium.com/@cdeniz/getting-started-working-with-ngrx-and-firebase-85832ad85889
我正在尝试在 Angular 中构建一个生命游戏应用程序。我有一个 grid
组件用于显示生命游戏网格,每个单元格要么死要么活(它本身没有任何生命游戏逻辑,只显示一个可点击的单元格网格)。 grid
组件有一个 2d gameplane: bool[][]
数组来表示 Game of Life 网格;每个单元格的信息都存储在该二维数组中。 grid component
还有一个 width: number
和一个 height: number
属性 来确定网格的尺寸。这两个都有一个 setter 根据传递的值调整 gameplane
的大小。
现在我想以某种方式 "share" 这 3 个属性与另一个不相关的组件 (control-panel
),这是通过服务完成的(但我不知道如何)。生命游戏逻辑不应在 grid
组件中。
我现在的问题是我需要能够读取和设置服务中的 3 个属性中的每一个,因为这是我计划放置逻辑的地方;例如,我需要能够读取组件的 gameplane
属性 以查看用户如何设置单元格的状态,这发生在 grid
组件本身,我还需要写入 gameplane
属性 以根据生命游戏的规则为下一个循环设置每个单元格的状态。
我尝试过使用 rxjs,但并没有真正理解我在做什么,这并没有给我想要的结果。这是一些代码:
grid.component.ts
// ... imports ...
@Component({
selector: "app-grid",
templateUrl: "./grid.component.html",
styleUrls: ["./grid.component.scss"]
})
export class GridComponent implements OnInit {
mousedown: boolean;
gameplane: boolean[][];
isMousedown: boolean = false;
private _width: number;
private _height: number;
// logic for click and mouseenter events...
grid.component.html(与问题无关)
<div>
<table
(mousedown)="isMousedown = true"
(mouseup)="isMousedown = false"
(mouseleave)="isMousedown = false"
>
<tr *ngFor="let row of gameplane; index as yCoord">
<td *ngFor="let cell of row; index as xCoord; trackBy:trackByTd"
(mousedown)="gameplane[yCoord][xCoord] = !gameplane[yCoord][xCoord]"
(mouseenter)="invertCellOnMouseEnter(yCoord, xCoord)"
class="cell"
>
</td>
</tr>
</table>
</div>
game-control.service.ts(我需要的一些功能)
@Injectable({
providedIn: 'root'
})
export class GameControlService {
evolveInterval: 1000;
isEvolving: boolean = false;
fillGameplane(state: boolean) {
// Fills each cell in the gameplane-array in grid.component with 'state' values.
}
randomizePlane() {
// Randomly fills each cell in the gameplane-array in grid.component with either true or false.
}
evolvePlane(){
// Reads the current value of the gameplane-array in grid.component and sets each cell's state
// depending on the state of the cell's neighbours according to the rules of the Game of Life
changeWidth(){
// Changes the width-poperty in grid.component
}
constructor() {}
}
- 既然你想在两个不相关的组件之间共享数据,你应该使用数据服务。本文非常详细地讨论了您应该如何操作(视频 + 代码示例)https://angularfirebase.com/lessons/sharing-data-between-angular-components-four-methods/
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
changeMessage(message: string) {
this.messageSource.next(message)
}
}
-------------------------------------------
@Component({
selector: 'component1'
})
export class ParentComponent implements OnInit {
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(data => console.log(data))
}
}
-------------------------------------------
@Component({
selector: 'component2'
})
export class SiblingComponent implements OnInit {
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(data => console.log(data))
this.data.changeMessage("Update the data")
}
}
注意:如果要共享大量复杂的数据,应该考虑使用redux,或者ngrx。这将需要一些学习。 https://medium.com/@cdeniz/getting-started-working-with-ngrx-and-firebase-85832ad85889