Angular BehaviorSubject点击添加任务按钮后无法切换任务视图
问题:Angular组件切换显示状态异常
我有以下Angular组件:
- ADD BUTTON(添加按钮组件)
- ADD TASK(添加任务组件)
- HEADER(头部组件)
- LIST TASK(任务列表组件)
同时使用MsgService服务实现组件间通信:ADD BUTTON通过该服务发送更新流,ADD TASK订阅这个更新。预期点击“添加任务”按钮时能切换添加任务视图的显示状态,但视图首次显示后无法切换隐藏。
ADD BUTTON组件代码
import { Component } from '@angular/core'; import { MsgService } from '../../services/msgservice.service'; @Component({ selector: 'app-addbutton', templateUrl: './addbutton.component.html', styleUrls: ['./addbutton.component.css'], }) export class AddbuttonComponent { toggletask: boolean = false; togglebutton: boolean = false; constructor(private msg: MsgService) {} subcribe() { console.log('sending msg'); this.msg.setMessage({ toggleAddTask: !this.toggletask, toggleButton: !this.togglebutton, }); } }
ADD BUTTON组件HTML
<div class="button"><button (click)="subcribe()"> ADD TASK </button></div>
ADD TASK组件代码
import { Component, OnInit } from '@angular/core'; import { Observable, Subscription } from 'rxjs'; import { MsgService } from 'src/app/services/msgservice.service'; @Component({ selector: 'app-addtask', template: ` <form *ngIf="toggletask"> <label for="taskdesc"> Task Name </label> <input type="text" id="taskdesc" /> <br /> <label for="date"> Date: </label> <input type="text" id="date" /><br /> <label for="complete"> Complete </label> <input type="checkbox" id="complete" /> </form> `, styles: [], }) export class AddtaskComponent implements OnInit { toggletask: boolean = false; togglebutton: boolean = false; subscription: Subscription; constructor(private msg: MsgService) { this.subscription = this.msg.getMessage().subscribe((val) => { this.toggletask = val.toggleAddTask; console.log('toggle task val ', val.toggleAddTask); this.togglebutton = val.toggleButton; }); } ngOnInit() { console.log('add task loaded inonint'); } toggle(): void { this.msg.getMessage().subscribe((val) => { this.toggletask = val.toggleAddTask; console.log('toggle task val ', val.toggleAddTask); this.togglebutton = val.toggleButton; }); } }
HEADER组件HTML
<p>header works!</p> <app-addbutton />
MsgService服务代码
import { Injectable } from '@angular/core'; import { Observable, BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class MsgService { toggletask: boolean = false; togglebutton: boolean = false; msg: BehaviorSubject<{ toggleAddTask: boolean; toggleButton: boolean }> = new BehaviorSubject<{ toggleAddTask: boolean; toggleButton: boolean }>({ toggleAddTask: false, toggleButton: false, }); constructor() {} setMessage(message: { toggleAddTask: boolean; toggleButton: boolean }): void { let tgtask: boolean = this.toggletask; let tgbutton: boolean = this.togglebutton; this.msg.next({ toggleAddTask: !tgtask, toggleButton: !tgbutton, }); console.log('in setmsg', this.msg.value); } getMessage(): Observable<{ toggleAddTask: boolean; toggleButton: boolean }> { console.log('in get', this.msg.value); return this.msg.asObservable(); } }
问题根源
- MsgService状态管理失效:服务内维护的
toggletask和togglebutton变量从未更新,每次调用setMessage时都是基于初始值false取反,永远只会发送true,无法切换回false。 - AddbuttonComponent本地状态冗余:组件内的状态变量没有和服务同步,传递给
setMessage的参数完全无效。
修复方案
1. 修正MsgService
移除冗余的本地变量,直接基于BehaviorSubject当前值进行状态切换:
import { Injectable } from '@angular/core'; import { Observable, BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class MsgService { private msg: BehaviorSubject<{ toggleAddTask: boolean; toggleButton: boolean }> = new BehaviorSubject<{ toggleAddTask: boolean; toggleButton: boolean }>({ toggleAddTask: false, toggleButton: false, }); constructor() {} setMessage(): void { const currentState = this.msg.value; this.msg.next({ toggleAddTask: !currentState.toggleAddTask, toggleButton: !currentState.toggleButton, }); console.log('in setmsg', this.msg.value); } getMessage(): Observable<{ toggleAddTask: boolean; toggleButton: boolean }> { console.log('in get', this.msg.value); return this.msg.asObservable(); } }
2. 简化AddbuttonComponent
移除本地状态变量,直接调用服务方法:
import { Component } from '@angular/core'; import { MsgService } from '../../services/msgservice.service'; @Component({ selector: 'app-addbutton', templateUrl: './addbutton.component.html', styleUrls: ['./addbutton.component.css'], }) export class AddbuttonComponent { constructor(private msg: MsgService) {} toggleAddTask() { console.log('sending msg'); this.msg.setMessage(); } }
3. 更新AddbuttonComponent HTML
修正按钮点击事件绑定:
<div class="button"><button (click)="toggleAddTask()"> ADD TASK </button></div>
4. 清理AddtaskComponent冗余代码
移除无用的toggle方法,并添加订阅销毁逻辑防止内存泄漏:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; import { MsgService } from 'src/app/services/msgservice.service'; @Component({ selector: 'app-addtask', template: ` <form *ngIf="toggletask"> <label for="taskdesc"> Task Name </label> <input type="text" id="taskdesc" /> <br /> <label for="date"> Date: </label> <input type="text" id="date" /><br /> <label for="complete"> Complete </label> <input type="checkbox" id="complete" /> </form> `, styles: [], }) export class AddtaskComponent implements OnInit, OnDestroy { toggletask: boolean = false; togglebutton: boolean = false; subscription: Subscription; constructor(private msg: MsgService) { this.subscription = this.msg.getMessage().subscribe((val) => { this.toggletask = val.toggleAddTask; console.log('toggle task val ', val.toggleAddTask); this.togglebutton = val.toggleButton; }); } ngOnInit() { console.log('add task loaded inonint'); } ngOnDestroy() { this.subscription.unsubscribe(); } }
内容的提问来源于stack exchange,提问作者user20604814
相关产品推荐
相关产品推荐

