我可以添加副作用来扫描吗

Can I add side-effects to scan

我有一个问题:“当鼠标按下时,创建一个矩形,移动时调整它的大小,当鼠标抬起时完成”。 我尝试使用 rxjs,但这不是很好的解决方案:

import { scan, mergeMap, takeUntil, fromEvent } from 'rxjs';

const mouseDown$ = fromEvent(document, 'mousedown');
const mouseUp$ = fromEvent(document, 'mouseup');
const mouseMove$ = fromEvent(document, 'mousemove');

function createNode() {
  const node = document.createElement('DIV');
  node.setAttribute('style', 'position: absolute; border: 1px solid red;');
  document.body.appendChild(node);
  return node;
}

mouseDown$
  .pipe(
    mergeMap(() => {
      return mouseMove$.pipe(
        takeUntil(mouseUp$),
        scan((node, e: MouseEvent) => {
          if (!node) {
            let x = null;
            x = createNode();
            x.style.top = `${e.clientY}px`;
            x.style.left = `${e.clientX}px`;
            return x;
          } else {
            node.style.bottom = `${e.clientY}px`;
            node.style.right = `${e.clientX}px`;
          }
          return node;
        }, null)
      );
    })
  )
  .subscribe(() => {});

问题是副作用被添加到方法“扫描” 对于这个问题,你有更好的解决方案吗?

如果你想避免内部管道副作用(这通常是一件好事)你可以将你的逻辑分成两个不同的 Observables/Subscriptions:

创建节点 Observable

let node = null

const createNode$ = mouseDown$.pipe(
  switchMapTo(mouseMove$.pipe(
    takeUntil(mouseUp$),
    take(1)
  ))
)

createNode$.subscribe(createNode)

function createNode(e: MouseEvent) {
  const node = document.createElement('DIV');
  node.setAttribute('style', 'position: absolute; border: 1px solid red;');
  document.body.appendChild(node);
  x.style.top = `${e.clientY}px`;
  x.style.left = `${e.clientX}px`;
  return node;
}

更新节点 Obsservable

const updateNode$ = mouseDown$.pipe(
  switchMapTo(mouseMove$.pipe(
    takeUntil(mouseUp$),
    skip(1)
  ))
)

updateNode$.subscribe(updateNode(node))

function updateNode(node: Node) {
  return function(e: MouseEvent) {
    node.style.bottom = `${e.clientY}px`;
    node.style.right = `${e.clientX}px`;
  }
}

与您的解决方案相比,我不喜欢上面的解决方案 - 它们在我看来都是平等的。这只是一种可能避免副作用的方法。关于何时以及为什么要避免副作用有多种意见。我个人尝试尽可能减少它们,但在某些情况下不值得这样做(或者我可能只是没有看到好的解决方案)。

我曾经问过一个关于的问题。答案可以为您提供一些详细信息,说明何时以及为何可以避免副作用。