我正在尝试使用Rxjs以及mousedown,mouseup和mousemove事件创建自己的单击,按住和拖动事件。我的尝试使用了许多从mousedown事件开始的流,每个流都带有一个takeUntil来侦听其他流的排放。基本上,一旦其中一个流“声明”了该动作(即通过了所有要求并发出了值),其他可观察对象就应该完成而不会产生任何排放。
我看了其他答案,认为可能与计时器异步运行有关,但它发生在不依赖计时器的流之间,例如拖动并单击。我一直在使用rxjs v6在codesandbox.io中玩耍。
takeUntil还必须坐在内部可观察对象上,因为我不希望外部可观察对象运行一次并完成。
代码如下所示:
const mouse_Down$ = fromEvent(document, "mousedown").pipe(
tap(event => event.preventDefault())
);
const mouse_Up$ = fromEvent(document, "mouseup").pipe(
tap(event => event.preventDefault())
);
const mouse_Move$ = fromEvent(document, "mousemove");
const mouse_drag$ = mouse_Down$
.pipe(
mergeMap(mouseDownEvent =>
mouse_Move$.pipe(takeUntil(merge(mouse_Up$, mouse_Hold$, mouse_drag$)))
)
).subscribe(event => console.log("Drag"));
const mouse_Hold$ = mouse_Down$
.pipe(
mergeMap(mouseDownEvent =>
timer(1000).pipe(takeUntil(merge(mouse_drag$, mouse_Click$)))
)
).subscribe(event => console.log("Hold"));
const mouse_Click$ = mouse_Down$
.pipe(
mergeMap(mouseDownEvent =>
mouse_Up$.pipe(takeUntil(mouse_drag$, mouse_Hold$))
)
).subscribe(event => console.log("Click"));
预期行为:
如果用户在mousedown事件的1s内移动鼠标,mouse_drag$
流应开始发出,mouse_Click$/mouse_Hold$
的内部可观察对象应完成(由于takeUntil(mouse_drag$)
而没有发出,等待下一个mouse_down$
发射。
如果在不移动mouse_Hold$
的情况下按住鼠标键超过1秒钟,并且mouse_drag$/mouse_click$
的内部可观察对象应该完成(由于takeUntil(mouse_Hold$)
而没有发出,等待下一个mouse_down$
发射。
实际行为::当前mouse_Drag$
将发出,mouse_Hold$
将在一秒钟后发出,mouse_Click$
将在释放按钮时发出。
我的问题是,为什么发射mouse_Drag$
的流不会导致mouse_Hold$
和mouse_Click$
的内部观察完成而不发射?
答案 0 :(得分:0)
收紧直到需要在链的尽头
这将取消整个链条。
const { fromEvent } = rxjs;
const { tap, takeUntil, mergeMap, merge } = rxjs.operators;
const mouse_Down$ = fromEvent(document, "mousedown").pipe(
tap(event => event.preventDefault())
);
const mouse_Up$ = fromEvent(document, "mouseup").pipe(
tap(event => event.preventDefault())
);
const mouse_Move$ = fromEvent(document, "mousemove");
const mouse_drag$ = mouse_Down$
.pipe(
mergeMap(mouseDownEvent =>
mouse_Move$
),
takeUntil(mouse_Up$)
).subscribe(event => console.log("Drag"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
答案 1 :(得分:0)
要澄清:
您无需完成任何操作,因为否则所有行为将仅起作用一次。 所以计划: 3. mouse_drag $-如果mousedown-检查mouseMove 1秒钟。如果mouseMove发出-切换到mouseMove值 4. mouse_Hold $-如果mouseDown-检查mouseMove 1秒钟。如果mouseMove不发光-切换到mouseHold并使其发出“ Hold”
let Rx = window['rxjs'];
const {defer, of, timer, fromEvent, merge, race} = Rx;
const {switchMap, repeat, tap, takeUntil, filter} = Rx.operators;
const {ajax} = Rx.ajax;
console.clear();
const mouse_Down$ = fromEvent(document, "mousedown");
const mouse_Up$ = fromEvent(document, "mouseup");
const mouse_Move$ = fromEvent(document, "mousemove");
const timer$ = timer(2000);
mouse_Hold$ = mouse_Down$.pipe(
switchMap((downEvent) => {
return timer$.pipe(
switchMap((time) => of('HOLD'))
);
}),
takeUntil(merge(mouse_Up$, mouse_Move$)),
repeat(mouse_Down$)
)
mouse_Hold$.subscribe(console.warn);
mouse_drags$ = mouse_Down$.pipe(
switchMap(() => mouse_Move$),
takeUntil(mouse_Up$, $mouse_Hold),
repeat(mouse_Down$)
)
mouse_drags$.subscribe(console.log);
这是一个codepen:https://codepen.io/kievsash/pen/oOmMwp?editors=0010