feat: support events in roots other than the main document

This commit is contained in:
Michael Rawlings 2022-05-05 14:37:41 -04:00
parent 50656ceec9
commit 4010c96cc9
5 changed files with 60 additions and 51 deletions

View File

@ -7,27 +7,27 @@
{
"name": "*",
"total": {
"min": 9152,
"gzip": 4103,
"brotli": 3744
"min": 9223,
"gzip": 4131,
"brotli": 3760
}
},
{
"name": "counter",
"user": {
"min": 388,
"gzip": 279,
"brotli": 258
"min": 393,
"gzip": 280,
"brotli": 250
},
"runtime": {
"min": 3076,
"gzip": 1487,
"brotli": 1341
"min": 3142,
"gzip": 1515,
"brotli": 1365
},
"total": {
"min": 3464,
"gzip": 1766,
"brotli": 1599
"min": 3535,
"gzip": 1795,
"brotli": 1615
}
},
{
@ -35,17 +35,17 @@
"user": {
"min": 247,
"gzip": 196,
"brotli": 209
"brotli": 206
},
"runtime": {
"min": 2151,
"gzip": 1174,
"brotli": 1046
"min": 2222,
"gzip": 1199,
"brotli": 1062
},
"total": {
"min": 2398,
"gzip": 1370,
"brotli": 1255
"min": 2469,
"gzip": 1395,
"brotli": 1268
}
},
{
@ -53,35 +53,35 @@
"user": {
"min": 1225,
"gzip": 625,
"brotli": 589
"brotli": 569
},
"runtime": {
"min": 5659,
"gzip": 2694,
"brotli": 2457
"min": 5730,
"gzip": 2724,
"brotli": 2473
},
"total": {
"min": 6884,
"gzip": 3319,
"brotli": 3046
"min": 6955,
"gzip": 3349,
"brotli": 3042
}
},
{
"name": "comments 💧",
"user": {
"min": 288,
"gzip": 226,
"brotli": 200
"gzip": 225,
"brotli": 198
},
"runtime": {
"min": 2285,
"gzip": 1229,
"brotli": 1098
"min": 2356,
"gzip": 1254,
"brotli": 1116
},
"total": {
"min": 2573,
"gzip": 1455,
"brotli": 1298
"min": 2644,
"gzip": 1479,
"brotli": 1314
}
}
]

View File

@ -8,6 +8,7 @@ import {
write,
bind,
queueInBranch,
queueHydrate,
Scope,
} from "../../../dom/index";
@ -51,7 +52,7 @@ export const walks = get + over(1) + get + over(1);
export const render = (scope: ComponentScope) => {
_apply_show(scope, true);
_apply_message(scope, "hi");
_hydrate(scope);
queueHydrate(scope, _hydrate);
};
export const _hydrate = (scope: ComponentScope) => {

View File

@ -3,6 +3,7 @@ import {
data,
createRenderFn,
queue,
queueHydrate,
bind,
write,
Scope,
@ -40,7 +41,7 @@ export const walks = get + next(1) + get + next(1);
export const render = (scope: ComponentScope) => {
execA(scope, 0);
execB(scope, 0);
hydrate(scope);
queueHydrate(scope, hydrate);
};
export const hydrate = (scope: ComponentScope) => {

View File

@ -3,6 +3,7 @@ import {
createRenderFn,
on,
queue,
queueHydrate,
write,
bind,
Scope,
@ -53,7 +54,7 @@ const execClickHandler = (
value: ComponentScope[Index.EVENT_HANDLER]
) => {
if (write(scope, Index.EVENT_HANDLER, value)) {
attachEventHandler(scope);
queueHydrate(scope, attachEventHandler);
}
};

View File

@ -1,9 +1,9 @@
type Unset = false | null | undefined;
type EventNames = keyof GlobalEventHandlersEventMap;
const delegatedByType = new Map<
string,
WeakMap<Element, Unset | ((...args: any[]) => void)>
const delegationRoots = new WeakMap<
Node,
Map<string, WeakMap<Element, Unset | ((...args: any[]) => void)>>
>();
const eventOpts: AddEventListenerOptions = {
@ -17,22 +17,28 @@ export function on<
| Unset
| ((ev: GlobalEventHandlersEventMap[T], target: Element) => void)
>(element: Element, type: T, handler: H) {
const delegated = delegatedByType.get(type);
if (delegated) {
delegated.set(element, handler);
} else {
delegatedByType.set(type, new WeakMap([[element, handler]]));
document.addEventListener(type, handleDelegated, eventOpts);
const delegationRoot = element.getRootNode();
let delegationEvents = delegationRoots.get(delegationRoot);
if (!delegationEvents) {
delegationRoots.set(delegationRoot, (delegationEvents = new Map()));
}
let delegationHandlers = delegationEvents.get(type);
if (!delegationHandlers) {
delegationEvents!.set(type, (delegationHandlers = new WeakMap()));
delegationRoot.addEventListener(type, handleDelegated, eventOpts);
}
delegationHandlers.set(element, handler);
}
function handleDelegated(ev: GlobalEventHandlersEventMap[EventNames]) {
let target = ev.target as Element | null;
const delegated = delegatedByType.get(ev.type)!;
if (target) {
let handler = delegated.get(target);
const delegationRoot = target.getRootNode();
const delegationEvents = delegationRoots.get(delegationRoot);
const delegationHandlers = delegationEvents!.get(ev.type!);
let handler = delegationHandlers!.get(target);
if (ev.bubbles) {
while (
@ -40,7 +46,7 @@ function handleDelegated(ev: GlobalEventHandlersEventMap[EventNames]) {
!ev.cancelBubble &&
(target = target!.parentElement!)
) {
handler = delegated.get(target);
handler = delegationHandlers!.get(target);
}
}