我无法使组件以角度删除自身。
我目前正在学习角度游戏,并开始了一个小型问候项目。该应用程序应如何工作:
目前,我已完成前两个步骤,并且一切正常。但是我不知道如何使子组件删除自身。来自React我知道,可以通过生命周期方法删除“组件”。有类似的东西吗?目前我找不到它,但是在销毁组件之前,我找到了被调用的方法“ OnDestroy()”。但是我如何正确销毁它?
父母:
import { Component, OnInit, ViewChild, Input } from '@angular/core';
@Component({
selector: 'app-greeter-service',
templateUrl: './greeter-service.component.html'
})
export class GreeterServiceComponent implements OnInit {
title = '';
currentUser = '';
isVisible = false;
currentUsers: any[] = [];
@ViewChild('newUser') inputField;
constructor() {}
greetingFunc(newUser : string) {
if(newUser) {
this.currentUsers.push(newUser);
console.log(this.currentUsers);
this.inputField.nativeElement.value='';
}
}
ngOnInit() {
this.title = 'Welcome to the Greeter!';
}
}
孩子:
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-was-greeted',
templateUrl: './was-greeted.component.html',
styleUrls: ['./was-greeted.component.scss']
})
export class WasGreetedComponent implements OnInit {
@Input() user: string;
constructor() { }
deleteMe() {
console.log("here should be the action");
}
ngOnInit() {
}
}
我如何“动态”向应用添加组件:
<div class="column" *ngFor="let user of currentUsers">
<app-was-greeted [user]="user"></app-was-greeted>
</div>
因此,为数组“ currentUsers”中的每个“推”创建一个组件。
答案 0 :(得分:4)
正如@cgTag所评论的那样,有很多方法可以处理此问题。一种方法是在您的@Query("select new my.package.MyDto("
+ "entity.status, "
+ "month(entity.date), "
+ "count(entity.status)) from MyEntity entity"
+ "where month(entity) = 12 "
+ "group by entity.status, month(entity.date) ")
List<MyDto> findGroupedByStatusInDecember();
中添加一个@Output
,它将发射到父组件。
然后在您WasGreetedComponent
中,您可以在数组中找到该元素并将其删除(请记住,您的数组应该是不可变的,因此您想创建该数组的新实例),这将导致{{1 }}重新评估和更新视图
GreeterServiceComponent
您的父组件模板随后将订阅此发射器
ngFor
该组件将需要处理@Component({
selector: 'app-was-greeted',
templateUrl: './was-greeted.component.html',
styleUrls: ['./was-greeted.component.scss']
})
export class WasGreetedComponent implements OnInit {
@Input() user: string;
@Output() delete: EventEmitter<string> = new EventEmitter();
constructor() { }
deleteMe() {
console.log("here should be the action");
this.delete.emit(user);
}
}
回调并将用户从数组中删除
<div class="column" *ngFor="let user of currentUsers">
<app-was-greeted [user]="user" (delete)="deleteUser($event)"></app-was-greeted>
</div>
就像我说的那样,这只是给猫加皮的许多方法之一。希望这会有所帮助。
答案 1 :(得分:1)
我无法使组件以角度删除自身。
比方说,呈现的HTML表示应用程序的 current 状态。有一个组件存在的状态,然后有一个不存在的状态。不要以为它是 delete 的行为,但是 state 发生了变化,此后该组件不再呈现。
- 输入您的姓名
状态没有任何问候。
- 已创建问候您的子组件。
状态至少有一个。
- 子组件包含用于删除自身的按钮
状态返回没有任何问候。
目前,我已完成前两个步骤,并且一切正常。但是我不知道如何使子组件删除自身。来自React,我知道可以通过某种生命周期方法删除“组件”。
如果您强制删除该组件,则页面上的组件将不再代表该应用程序的当前状态。拥有 microstates 的地方很好,例如,像是模式对话框。对话框本身具有其自己的状态,并且对话框的显示具有相对于该微状态的生命周期。
在您的示例中,我认为情况并非如此。
currentUsers: any[] = [];
以上是您的 state 变量。该 array 的值表示将在HTML中呈现的内容。您可以提出一些问题,答案可以帮助您。
让我们回答这些问题
- 谁拥有国家?
GreeterServiceComponent
组件是状态的所有者,在这种情况下,状态表示为数组。在Web组件中,我们将此称为组件的状态。这是组件的内部问题。
- 谁可以改变该状态?
我们只希望GreeterServiceComponent
对此状态进行更改。类之外的源代码不应直接访问它并对其进行突变。我们可以说该组件负责处理此内部状态的存储和生命周期。
- 我如何要求国家所有者进行更改?
这是我们介绍Angular细节的地方。在Angular中,我们有多种方式在组件之间进行通信。在这种情况下,我们希望 child 组件与 parent 组件进行通信,以使其应更改其内部状态。我们要告诉父母不要再打招呼了。解决此问题的每种方法都有其优点和缺点,由您决定哪种方法适合您。
Angular中的组件可以具有一个@Output()
,该WasGreetedComponent
在父组件的模板中执行表达式。这与将回调函数传递给React组件的属性相同。
在@Output()
public closed: Subject<void>() = new Subject();
deleteMe() { this.closed.next(); }
中,您将添加:
GreeterServiceComponent
在<div class="column" *ngFor="let user of currentUsers">
<app-was-greeted [user]="user"
(closed)="currentUsers = currentUsers.filter(u=>u!==user)">
</app-was-greeted>
</div>
模板中,您将更改:
ChangeDetectorRef
Angular中的子组件可以通过构造函数注入自己的父组件,然后您可以直接通知父组件。
此方法绕过了模板,对父级所做的任何更改都可能需要更新视图。因此,建议父母使用GreeterServiceComponent
将其视图标记为“ dity”。
在 public deleteUser(user: any) {
this.currentUsers = this.currentUsers.filter(u=>u !== user);
this.changeDetectorRef.markForCheck();
}
中,您将添加:
WasGreetedComponent
在 constructor(parent: GreeterServiceComponent) {}
deleteMe() { this.parent.deleteUser(this.user); }
中,您将添加:
@Injectable({provideIn: 'root'})
export class StateService {
public users: BehaviorSubject<any[]> = new BehaviorSubject([]);
public addUser(user: any) {
this.users
.pipe(first())
.subject(users => this.users.next([...users, user]));
}
public removeUser(user: any) {
this.users
.pipe(first())
.subject(users => this.users.next(users.filter(u=>u !== user)));
}
}
最后一种方法是使用反应式编程,其中使用 observables 来允许消费者监视应用程序状态的变化。这样做的好处是,状态由外部服务拥有并由管理。诸如Redux / NGRX / NGXS之类的流行服务在Angular / React / Vue框架中大量使用。使用状态存储有很多优点,但是要掌握它们是困难的框架,对于一个小型项目而言,这通常是过大的。一旦开始使用它们,就很难退出使用。
我们可以创建自己的小版本作为演示。
您将添加代表您的应用程序状态的服务。
GreeterServiceComponent
现在,在您的@Component({...})
export class GreeterServiceComponent implements OnInit {
constructor(public state: StateService) {}
greetingFunc(newUser : string) {
if(newUser) {
this.state.addUser(newUser);
}
}
中,它将不再是该州的<所有者> 。我们将注入以上服务并允许该服务对其进行管理。
GreeterServiceComponent
在async
模板中,我们将使用StateService
管道直接从GreeterServiceComponent
显示用户的当前状态。我们这样做是因为该服务持有关于当前状态的真相。 <div class="column" *ngFor="let user of state.users | async">
<app-was-greeted [user]="user"></app-was-greeted>
</div>
组件将不关心它的变化,因为它不拥有或管理它。
WasGreetedComponent
StateService
组件将使用@Component({...})
export class WasGreetedComponent implements OnInit {
constructor(public state: StateService) {}
deleteMe() {
this.state.removeUser(this.user);
}
更改当前的状态。该组件不关心其父组件。您可以在应用程序中移动该组件,它仍然可以正常运行。这是一个重要的好处,因为上述其他方法取决于DOM本身的结构。因此,移动组件将需要在其他位置进行更改以保持组件正常工作。
{{1}}
答案 2 :(得分:0)
让组件具有一个@Output参数,父组件会监听该@Output参数并将其从currentUsers中删除,或者为* ngFor添加附加逻辑,以便在循环中绘制元素时忽略它。像这样的老兄吗?
<div class="column" *ngFor="let user of currentUsers; let i = index">
<app-was-greeted *ngIf="shouldDisplay(i)" (buttonClick)="removeMe(i)" [user]="user">
</app-was-greeted>
</div>