BehaviorSubject子属性重置失败:整体变量可正常重置的技术求助
问题:切换账户活跃状态后班级学生无法重置为原始数量
问题现象
- 账户未激活(初始状态):6名学生、2个班级,第二个班级包含6名学生
- 账户激活后:学生列表变为4名,第二个班级学生数量同步变为4名,此步骤正常
- 切换回未激活状态:学生列表恢复为6名,但第二个班级的学生数量无法重置回6名
问题根源
getSections方法的map操作中,直接修改了BehaviorSubject存储的原始数据引用:
sections[1].child = sections[1].child.filter(...)
这行代码会直接覆盖原始的child数组,导致后续切换回未激活状态时,没有原始数据可以恢复。
而getStudents中使用students = students.filter(...)是创建新数组返回,没有修改BehaviorSubject内的原始数据,因此可以正常重置。
修复方案
处理sections时,创建数组和对象的副本,避免修改原始数据:
import { BehaviorSubject, combineLatest, filter, map, Observable } from 'rxjs'; interface arrType { id?: string; name?: string; child?: arrType[]; } export class NavSer { constructor() {} toppers = ['first', 'second']; students = new BehaviorSubject<arrType[]>([]); sections = new BehaviorSubject<arrType[]>([]); isActive = new BehaviorSubject<boolean>(false); init = () => { const arr = [ { id: '1', name: 'first' }, { id: '2', name: 'second' }, { id: '3', name: 'third' }, { id: '4', name: 'forth' }, { id: '5', name: 'fifth' }, { id: '6', name: 'sixth' }, ]; this.sections.next([ { id: 's1', name: 'iFirst' }, { id: 's2', name: 'iSecond', child: arr }, ]); this.students.next(arr); }; getSections(): Observable<arrType[]> { return combineLatest([ this.sections.asObservable(), this.isActive.asObservable(), ]).pipe( filter(([sections]) => sections !== undefined), map(([sections, isActive]) => { // 创建sections数组的浅拷贝,避免修改原始数据 const updatedSections = [...sections]; if (isActive) { // 创建新的班级对象替换原项,修改child数组时不影响原始数据 updatedSections[1] = { ...updatedSections[1], child: updatedSections[1].child.filter(obj => !this.toppers.some(obj2 => obj.name === obj2) ) }; } return updatedSections; }) ); } getStudents(): Observable<arrType[]> { return combineLatest([ this.students.asObservable(), this.isActive.asObservable(), ]).pipe( filter(([students]) => students !== undefined), map(([students, isActive]) => { if (isActive) { return students.filter(obj => !this.toppers.some(obj2 => obj.name === obj2) ); } return students; }) ); } changeAccount = () => { this.isActive.next(!this.isActive.value); }; } var n = new NavSer(); n.init(); n.getStudents().subscribe((data) => { console.log('students', data); }); n.getSections().subscribe((data) => { console.log('sections', data); }); document .getElementById('changeAccount') .addEventListener('click', n.changeAccount);
修复说明
- 使用
const updatedSections = [...sections]创建sections数组的浅拷贝,切断与原始数据的引用关联 - 处理第二个班级时,通过
{ ...updatedSections[1], child: 过滤后的数组 }创建新的班级对象,避免直接修改原始班级的child数组 - 未激活状态下直接返回拷贝后的原始数据结构,保证BehaviorSubject内的原始数据始终未被修改,切换状态时能正常恢复
内容的提问来源于stack exchange,提问作者akash
相关产品推荐
相关产品推荐

