【问题标题】:how to switch the "order" property of 2 items in this array/list?如何切换此数组/列表中 2 个项目的“顺序”属性?
【发布时间】:2026-02-06 06:50:01
【问题描述】:
class item {
  name: string;
  order: number;
}
let onUp = new Rx.Subject<item>();
let list = new Rx.BehaviorSubject<item>([
  { name: "7", order: 70 },
  { name: "2", order: 20 },
  { name: "5", order: 50 },
  { name: "3", order: 30 },
  { name: "4", order: 40 },
  { name: "6", order: 60 },
  { name: "1", order: 10 }
]);
list.subscribe(console.log);
onUp.subscribe(anItem => {
  let numberList: item[];
  list
    .take(1)
    .map(x => x.sort((a, b) => a.order - b.order))
    .subscribe(ddList => (numberList = ddList));
  let index = numberList.indexOf(numberList.find(num => num.order == anItem));
  let ddvalue = numberList[index];
  let preddvalue = numberList[index - 1];

  let preddvalueOrder = preddvalue.order;
  preddvalue.order = ddvalue.order;
  ddvalue.order = preddvalue.order;

  list.next(numberList);
});

onUp.next(30);

与列表中的另一个对象交换“订单”值的反应方式是什么?

我有一堆物品应该可以重新排序。

项目的顺序基于项目列表中项目对象的 order 属性。 我通过切换两个项目的 order 属性来重新排序项目。 在示例代码中,onUp Subject 发出了一个 orderNumber,该 orderNumber 应该与上面的 item 切换(按 order 属性排序)

示例代码有效,只是因为第二次订阅是异步的,因此它可能是不好的做法。 另一种方法是在外部订阅内部的订阅内部进行重新排序,但这也是不好的做法(不知道为什么除了它是一个凌乱的巢穴之外)。

我总是看到 flatMap,但如果我理解正确,第二次订阅只会使用第一次订阅中的数据来获取数据。 在这种情况下,我需要来自第一个和第二个主题的数据来切换这两个项目,并将新列表推送到列表主题。

【问题讨论】:

    标签: rxjs


    【解决方案1】:

    啊.... 维护 2 个列表对您来说可以吗?一个是未排序的,另一个总是监听未排序的变化并排序。

    const list = new Rx.BehaviorSubject([
      { name: "7", order: 70 },
      { name: "2", order: 20 },
      { name: "5", order: 50 },
      { name: "3", order: 30 },
      { name: "4", order: 40 },
      { name: "6", order: 60 },
      { name: "1", order: 10 }
    ]);
    const sortedList = new Rx.BehaviorSubject([]);
    const onUp = new Rx.BehaviorSubject(0);
    
    list
      .map(x => x.sort((a, b) => a.order - b.order))
      .subscribe(x => sortedList.next(x));
    
    sortedList.subscribe(console.log);
    
    onUp.subscribe(x => {
      const idx  = sortedList.getValue()
        .findIndex(itm => itm.order === x);
      
      if (idx < 1) return;
      
      const list = sortedList.getValue();
      
      const prev = list[idx - 1].order;
      const curr = list[idx].order;
      
      list[idx].order = prev;
      list[idx - 1].order = curr;
      
      sortedList.next(list);
    });
    
    onUp.next(30);
    onUp.next(70);
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 谢谢你,@Chybie。但我实际上是在切换数组中 2 个相邻对象的 order 属性。
    【解决方案2】:

    BehaviorSubjectgetValue() 也是不好的做法(Ben Lesh 在我的资料中这么说)。阅读 withLatestFromcombineLatest 以组合两个 observables。

    class item {
      name: string;
      order: number;
    }
    let onUp = new Rx.Subject<item>();
    let list = new Rx.BehaviorSubject<item[]>([
      { name: "7", order: 70 },
      { name: "2", order: 20 },
      { name: "5", order: 50 },
      { name: "3", order: 30 },
      { name: "4", order: 40 },
      { name: "6", order: 60 },
      { name: "1", order: 10 }
    ]);
    list.subscribe(console.log);
    // onUp.subscribe(anItem => {
    onUp
      .withLatestFrom(list, (item, itemList) => {
        return { item: item, itemList: itemList };
      })
      .subscribe(itemWithList => {
        let numberList: item[] = itemWithList.itemList.sort(
          (a, b) => a.order - b.order
        );
        let orderToUp: number = itemWithList.item;
    
        let index = numberList.findIndex(x => x.order === orderToUp);
        let ddvalue = numberList[index];
        let preddvalue = numberList[index - 1];
        console.log(ddvalue);
    
        let preddvalueOrder = preddvalue.order;
        preddvalue.order = ddvalue.order;
        ddvalue.order = preddvalueOrder;
    
        list.next(numberList);
      });
    
    onUp.next(30);
    

    在此处粘贴: https://emeraldwalk.github.io/rxjs-playground/#

    来源: https://*.com/a/45227115

    【讨论】: