Skip to content

Commit 855c2e7

Browse files
committedJan 17, 2025
streamline dom render
1 parent 468fb45 commit 855c2e7

File tree

3 files changed

+67
-42
lines changed

3 files changed

+67
-42
lines changed
 

‎src/utils/component.ts

+49-31
Original file line numberDiff line numberDiff line change
@@ -66,46 +66,64 @@ export function renderElement(
6666
placeholder: Comment | Node | null = null,
6767
skipRegistration = false,
6868
) {
69+
if (isFn(el)) {
70+
// @ts-expect-error
71+
el = resolveRenderable(el);
72+
}
6973
if (isEmpty(el) || el === '') {
7074
return;
7175
}
72-
if (!isArray(el)) {
73-
if (isPrimitive(el)) {
74-
let node = api.text(el);
75-
if (skipRegistration !== true) {
76-
ctx[RENDERED_NODES_PROPERTY].push(node);
77-
}
78-
api.insert(target, node, placeholder);
79-
} else if ((el as HTMLElement).nodeType) {
80-
if (skipRegistration !== true) {
81-
ctx[RENDERED_NODES_PROPERTY].push(el as Node);
82-
}
83-
api.insert(target, el as Node, placeholder);
84-
} else if ($nodes in el) {
85-
el[$nodes].forEach((node) => {
86-
// @ts-expect-error el.ctx
87-
renderElement(api, el.ctx, target, node, placeholder);
88-
});
89-
el[$nodes].length = 0;
90-
// el.ctx![RENDERED_NODES_PROPERTY].reverse();
91-
} else if (isFn(el)) {
92-
// @ts-expect-error
93-
renderElement(api, ctx, target, resolveRenderable(el), placeholder, skipRegistration);
94-
} else if (isTagLike(el)) {
95-
const node = api.text('');
76+
77+
const renderedNodes = ctx[RENDERED_NODES_PROPERTY];
78+
79+
if (isPrimitive(el)) {
80+
const node = api.text(el);
81+
if (!skipRegistration) {
9682
ctx[RENDERED_NODES_PROPERTY].push(node);
97-
api.insert(target, node, placeholder);
98-
registerDestructor(ctx, opcodeFor(el, (value) => {
99-
api.textContent(node, String(value ?? ''));
100-
}));
101-
} else {
102-
throw new Error(`Unknown element type ${el}`);
10383
}
104-
} else {
84+
api.insert(target, node, placeholder);
85+
return;
86+
}
87+
88+
if ((el as HTMLElement).nodeType) {
89+
if (!skipRegistration) {
90+
renderedNodes.push(el as Node);
91+
}
92+
api.insert(target, el as Node, placeholder);
93+
return;
94+
}
95+
96+
if ($nodes in el) {
97+
const nodes = el[$nodes];
98+
const elCtx = el.ctx!;
99+
for (let i = 0; i < nodes.length; i++) {
100+
renderElement(api, elCtx, target, nodes[i], placeholder);
101+
}
102+
nodes.length = 0;
103+
return;
104+
}
105+
106+
if (isTagLike(el)) {
107+
const node = api.text('');
108+
renderedNodes.push(node);
109+
registerDestructor(
110+
ctx,
111+
opcodeFor(el, (value) => {
112+
api.textContent(node, String(value ?? ''));
113+
}),
114+
);
115+
api.insert(target, node, placeholder);
116+
return;
117+
}
118+
119+
if (Array.isArray(el)) {
105120
for (let i = 0; i < el.length; i++) {
106121
renderElement(api, ctx, target, el[i], placeholder, true);
107122
}
123+
return;
108124
}
125+
126+
throw new Error(`Unknown element type ${el}`);
109127
}
110128

111129
export function renderComponent(

‎src/utils/dom.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -621,12 +621,16 @@ function _DOM(
621621
renderElement(api, ctx, appendRef!, children);
622622
}
623623
} else {
624-
// @ts-expect-error children type mismatch
625-
renderElement(api, ctx, appendRef!, children);
624+
for (let i = 0; i < children.length; i++) {
625+
// @ts-expect-error children type mismatch
626+
renderElement(api, ctx, appendRef!, children[i], null, true);
627+
}
626628
}
627629
} else {
628-
// @ts-expect-error children type mismatch
629-
renderElement(api, ctx, element, children);
630+
for (let i = 0; i < children.length; i++) {
631+
// @ts-expect-error children type mismatch
632+
renderElement(api, ctx, element, children[i], null, true);
633+
}
630634
}
631635

632636
if (destructors.length) {

‎src/utils/shared.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@ export function isFn(value: unknown): value is Function {
4444
export function isEmpty(value: unknown): value is null | undefined {
4545
return value === null || value === undefined;
4646
}
47+
4748
export function isPrimitive(value: unknown): value is string | number {
48-
const vType = typeof value;
49-
return (
50-
vType === 'string' ||
51-
vType === 'number' ||
52-
vType === 'boolean' ||
53-
vType === 'bigint'
54-
);
49+
switch (typeof value) {
50+
case 'string':
51+
case 'number':
52+
case 'boolean':
53+
case 'bigint':
54+
return true;
55+
default:
56+
return false;
57+
}
5558
}
5659

5760
export function isTagLike(child: unknown): child is AnyCell {

0 commit comments

Comments
 (0)