You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);

修复说明

  1. 使用const updatedSections = [...sections]创建sections数组的浅拷贝,切断与原始数据的引用关联
  2. 处理第二个班级时,通过{ ...updatedSections[1], child: 过滤后的数组 }创建新的班级对象,避免直接修改原始班级的child数组
  3. 未激活状态下直接返回拷贝后的原始数据结构,保证BehaviorSubject内的原始数据始终未被修改,切换状态时能正常恢复

内容的提问来源于stack exchange,提问作者akash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 16:05:17