Defining global event type #14433
Replies: 3 comments 1 reply
-
|
The API I'm imagining might look something like this: function registerMove(element, handler) {
let scrollHandler = event => {...}; // calls handler()
element.addEventListener('scroll', scrollHandler);
// other event types
// ...
// returns an un-register callback
return () => {
element.removeEventListener('scroll', scrollHandler);
// etc.
};
}
app.addCustomEvent("move", registerMove); |
Beta Was this translation helpful? Give feedback.
-
|
Hello @geraintluff, Working with Vue reactivity system and compilers can sometimes present interesting edge cases. A few quick things to consider regarding this topic:
I highly recommend checking out the Vue DevTools extension to inspect the component tree and verify if the state is updating as expected. Let me know if you want to dig deeper into the specific component logic. Hope this points you in the right direction! Let me know how it goes. Happy coding! |
Beta Was this translation helpful? Give feedback.
-
|
Not as a global custom On a native element, this: <div @move="onMove" />means Vue will register a DOM event listener for an actual DOM event named The Vue way to do this is a custom directive: import type { Directive } from "vue";
type MoveEvent = {
dx: number;
dy: number;
source: "pointer" | "keyboard" | "wheel";
};
type MoveHandler = (event: MoveEvent) => void;
export const vMove: Directive<HTMLElement, MoveHandler> = {
mounted(el, binding) {
let lastX = 0;
let lastY = 0;
let dragging = false;
const emit = (event: MoveEvent) => {
binding.value(event);
};
const pointerdown = (event: PointerEvent) => {
dragging = true;
lastX = event.clientX;
lastY = event.clientY;
el.setPointerCapture?.(event.pointerId);
};
const pointermove = (event: PointerEvent) => {
if (!dragging) {
return;
}
emit({
dx: event.clientX - lastX,
dy: event.clientY - lastY,
source: "pointer",
});
lastX = event.clientX;
lastY = event.clientY;
};
const pointerup = () => {
dragging = false;
};
const wheel = (event: WheelEvent) => {
emit({
dx: event.deltaX,
dy: event.deltaY,
source: "wheel",
});
};
const keydown = (event: KeyboardEvent) => {
const step = event.shiftKey ? 10 : 1;
const map: Record<string, [number, number]> = {
ArrowLeft: [-step, 0],
ArrowRight: [step, 0],
ArrowUp: [0, -step],
ArrowDown: [0, step],
};
const delta = map[event.key];
if (delta) {
emit({
dx: delta[0],
dy: delta[1],
source: "keyboard",
});
}
};
el.addEventListener("pointerdown", pointerdown);
el.addEventListener("pointermove", pointermove);
el.addEventListener("pointerup", pointerup);
el.addEventListener("pointercancel", pointerup);
el.addEventListener("wheel", wheel);
el.addEventListener("keydown", keydown);
if (!el.hasAttribute("tabindex")) {
el.tabIndex = 0;
}
(el as any).__moveCleanup = () => {
el.removeEventListener("pointerdown", pointerdown);
el.removeEventListener("pointermove", pointermove);
el.removeEventListener("pointerup", pointerup);
el.removeEventListener("pointercancel", pointerup);
el.removeEventListener("wheel", wheel);
el.removeEventListener("keydown", keydown);
};
},
unmounted(el) {
(el as any).__moveCleanup?.();
},
};Register it globally: app.directive("move", vMove);Then use it like this: <div
v-move="(move) => { posX += move.dx; posY += move.dy }"
/>So the syntax would be If you really want el.dispatchEvent(
new CustomEvent("move", {
detail: { dx, dy },
}),
);and then this would work: <div @move="(event) => { posX += event.detail.dx; posY += event.detail.dy }" />But I would prefer |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Is there a way to define a global event type which is translated from a DOM event? For example, I'd like to define
@movesuch that I can write:I'd then have a single global definition for the "move" event which listened for mouse-drag, keyboard and scroll-wheel DOM events, and translated them all to common dx/dy values.
The idea is to concisely provide consistent interactivity across my app, instead of having to separately map drag/keyboard/scroll for each control. Is this possible?
Beta Was this translation helpful? Give feedback.
All reactions