From 843a64ebd975d1f25dabf189e8a9a499e4ed3ca0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=88=E8=B6=85=E6=B6=9B?=
<10857776+chaoling83@user.noreply.gitee.com>
Date: Sun, 18 Feb 2024 07:06:57 +0000
Subject: [PATCH] !144 fix(no-vdom): optimize dom.ts file * fix(no-vdom):
optimize dom.ts file * Merge branch 'reactive' of
https://gitee.com/openInula/inula into reactive * fix(no-vdom): modify
$$style * fix(no-vdom): modify test name * Merge branch 'reactive' of
https://gitee.com/openInula/inula into reactive * fix(no-vdom): modify event
* Merge branch 'reactive' of https://gitee.com/openInula/inula into reactive
* fix(no-vdom): modify test code's name rule * Merge branch 'reactive' of
https://gitee.com/openInula/inula into reactive * fix(no-vdom): delete
no-vnode module * fix(no-vdom): update render function * Merge branch
'reactive' of https://gitee.com/openInula/inula into reactive * Merge branch
'reactive' of https://gitee.com/openInula/inula into reactive * Merge
remote-tracking branch 'origin/reactive' into reactive * fix(no-vdom): add TS
* fix(no-vdom): change js 2 ts
---
packages/inula-novdom/src/dom.ts | 131 ++++++++++--------
packages/inula-novdom/tests/For.bench.tsx | 6 +-
packages/inula-novdom/tests/For.test.tsx | 10 +-
.../inula-novdom/tests/conditions.test.tsx | 18 +--
packages/inula-novdom/tests/event.test.tsx | 6 +-
packages/inula-novdom/tests/render.test.tsx | 66 ++++-----
6 files changed, 129 insertions(+), 108 deletions(-)
diff --git a/packages/inula-novdom/src/dom.ts b/packages/inula-novdom/src/dom.ts
index ff11474e..5a955cae 100644
--- a/packages/inula-novdom/src/dom.ts
+++ b/packages/inula-novdom/src/dom.ts
@@ -37,118 +37,139 @@ export function template(html: string): () => Node {
};
}
-export function insert(parent: Node, maybeSignal: any, marker?: Node, initial?: any[]): any {
- if (marker !== undefined && !initial) {
+export function insert(parent: Node, maybeSignal: any, marker?: Node) {
+ let initial: any;
+ if (marker !== undefined) {
initial = [];
}
if (isReactiveObj(maybeSignal)) {
- watchRender((current: any) => {
- return insertExpression(parent, maybeSignal.get(), current, marker);
+ watchRender((prevValue: any) => {
+ return insertExpression(parent, maybeSignal.get(), prevValue, marker);
}, initial);
} else {
- return insertExpression(parent, maybeSignal, initial, marker);
+ insertExpression(parent, maybeSignal, initial, marker);
}
}
-function watchRender(fn: (value: any) => any, prevValue: any): void {
- let nextValue = prevValue;
+function watchRender(fn: (value: any) => any, initial?: any): void {
+ let prevValue = initial;
watch(() => {
- nextValue = fn(nextValue);
+ prevValue = fn(prevValue);
});
}
-function insertExpression(parent, value, current, marker, unwrapArray) {
- while (typeof current === 'function') current = current();
- if (value === current) return value;
+function insertExpression(parent: Node, value: any, prevValue: any, marker?: Node): any {
+ let result: any;
+ while (typeof prevValue === 'function') {
+ prevValue = prevValue();
+ }
- const t = typeof value,
- multi = marker !== undefined;
+ if (value === prevValue) {
+ return value;
+ }
+
+ const t: string = typeof value;
+ const multi: boolean = marker !== undefined;
if (t === 'string' || t === 'number') {
if (t === 'number') value = value.toString();
if (multi) {
- let node = current[0];
+ let node: Node | Text = prevValue[0];
if (node && node.nodeType === 3) {
- node.data = value;
+ (node as Text).data = value;
} else {
node = document.createTextNode(value);
}
- current = cleanChildren(parent, current, marker, node);
+ result = cleanChildren(parent, prevValue, marker, node);
} else {
- if (current !== '' && typeof current === 'string') {
- current = parent.firstChild.data = value;
- } else current = parent.textContent = value;
+ if (prevValue !== '' && typeof prevValue === 'string') {
+ result = (parent.firstChild as Text).data = value;
+ } else {
+ result = parent.textContent = value;
+ }
}
} else if (value == null || t === 'boolean') {
- current = cleanChildren(parent, current, marker);
+ result = cleanChildren(parent, prevValue, marker);
} else if (t === 'function') {
// 在watch里面执行
- watch(() => {
+ watchRender((prev) => {
let v = value();
while (isReactiveObj(v)) {
v = v.get();
}
+ result = insertExpression(parent, v, prev, marker);
+ return result;
+ }, prevValue);
- current = insertExpression(parent, v, current, marker);
- });
- return () => current;
+ return () => result;
} else if (Array.isArray(value)) {
- // return [() => {}, () => {}, ...]
- const array = [];
- const currentArray = current && Array.isArray(current);
- if (normalizeIncomingArray(array, value, current, unwrapArray)) {
- watchRender(() => (current = insertExpression(parent, array, current, marker, true)));
- return () => current;
+ // value:[() => {}, () => {}, ...]
+ const array: any[] = [];
+ const isPrevArray: boolean = prevValue && Array.isArray(prevValue);
+ if (flattenArray(array, value)) {
+ watchRender((prev) => {
+ result = insertExpression(parent, array, prev, marker);
+ return result;
+ }, prevValue);
+
+ return () => result;
}
- if (array.length === 0) {
- // 当前没有节点
- current = cleanChildren(parent, current, marker);
- if (multi) return current;
- } else if (currentArray) {
- if (current.length === 0) {
+ if (array.length === 0) { // 当前没有节点
+ result = cleanChildren(parent, prevValue, marker);
+ if (multi) {
+ return result;
+ }
+ } else if (isPrevArray) {
+ if (prevValue.length === 0) {
appendNodes(parent, array, marker); // 原来没有节点
} else {
- reconcileArrays(parent, current, array); // 原本有节点,现在也有节点
+ reconcileArrays(parent, prevValue, array); // 原本有节点,现在也有节点
}
} else {
- current && cleanChildren(parent);
+ if (prevValue) {
+ parent.textContent = ''; // 原来有节点,但不是数组
+ }
+
appendNodes(parent, array);
}
- current = array;
- } else if (value.nodeType) {
- if (Array.isArray(current)) {
- if (multi) return (current = cleanChildren(parent, current, marker, value));
- cleanChildren(parent, current, null, value);
- } else if (current == null || current === '' || !parent.firstChild) {
+ result = array;
+ } else if (value.nodeType) { // 是Node节点
+ if (Array.isArray(prevValue)) {
+ if (multi) {
+ return cleanChildren(parent, prevValue, marker, value);
+ } else {
+ cleanChildren(parent, prevValue, null, value);
+ }
+ } else if (prevValue == null || prevValue === '' || !parent.firstChild) {
parent.appendChild(value);
} else {
parent.replaceChild(value, parent.firstChild);
}
- current = value;
+ result = value;
}
- return current;
+ return result;
}
-function cleanChildren(parent: Node, current: Node[], marker?: Node, replacement?: Node): Node[] {
+function cleanChildren(parent: Node, prevNodes: Node[], marker?: Node, replacement?: Node): Node[] {
if (marker === undefined) {
parent.textContent = '';
return [];
}
const node = replacement || document.createTextNode('');
- if (current.length) {
+ if (prevNodes.length) {
let inserted = false;
- for (let i = current.length - 1; i >= 0; i--) {
- const el = current[i];
+ for (let i = prevNodes.length - 1; i >= 0; i--) {
+ const el = prevNodes[i];
if (node !== el) {
const isParent = el.parentNode === parent;
if (!inserted && !i) {
isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker);
} else {
- isParent && el.remove();
+ isParent && (el as ChildNode).remove();
}
} else {
inserted = true;
@@ -168,7 +189,7 @@ function appendNodes(parent: Node, array: Node[], marker: Node | null = null): v
}
// 拆解数组,如:[[a, b], [c, d], ...] to [a, b, c, d]
-function normalizeIncomingArray(normalized: Node[], array: any[]): boolean {
+function flattenArray(normalized: Node[], array: any[]): boolean {
let dynamic = false;
for (let i = 0, len = array.length; i < len; i++) {
const item = array[i];
@@ -177,7 +198,7 @@ function normalizeIncomingArray(normalized: Node[], array: any[]): boolean {
// matches null, undefined, true or false
// skip
} else if (Array.isArray(item)) {
- dynamic = normalizeIncomingArray(normalized, item) || dynamic;
+ dynamic = flattenArray(normalized, item) || dynamic;
} else if ((t = typeof item) === 'string' || t === 'number') {
normalized.push(document.createTextNode(item));
} else if (t === 'function') {
@@ -225,7 +246,7 @@ export default function reconcileArrays(parentNode: Node, oldChildren: Node[], n
// 新节点全部和新节点相同(不是完全相同, 如:旧 abefcd 新 abcd)
while (oStart < oEnd) {
if (!map || !map.has(oldChildren[oStart])) {
- oldChildren[oStart].remove();
+ (oldChildren[oStart] as ChildNode).remove();
}
oStart++;
}
@@ -276,7 +297,7 @@ export default function reconcileArrays(parentNode: Node, oldChildren: Node[], n
oStart++;
}
} else {
- oldChildren[oStart++].remove();
+ (oldChildren[oStart++] as ChildNode).remove();
}
}
}
diff --git a/packages/inula-novdom/tests/For.bench.tsx b/packages/inula-novdom/tests/For.bench.tsx
index 3771a559..db2c4a3a 100644
--- a/packages/inula-novdom/tests/For.bench.tsx
+++ b/packages/inula-novdom/tests/For.bench.tsx
@@ -20,7 +20,7 @@ import {
setAttribute as $$attr,
effect as $$effect,
} from '../src/dom';
-import { runComponent as $$runComponent, render as $$render } from '../src/core';
+import { runComponent as $$runComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$on } from '../src/event';
import { For } from '../src/components/For';
@@ -100,7 +100,7 @@ bench('For', () => {
* );
* };
*
- * $$render(() => , document.getElementById("app"));
+ * render(() => , document.getElementById("app"));
*/
// 编译后:
@@ -229,7 +229,7 @@ bench('For', () => {
return _el$5;
})();
};
- $$render(() => $$runComponent(Main, {}), container);
+ render(() => $$runComponent(Main, {}), container);
$$delegateEvents(['click']);
container.querySelector('#run').click();
diff --git a/packages/inula-novdom/tests/For.test.tsx b/packages/inula-novdom/tests/For.test.tsx
index 46c4b94f..532a39a9 100644
--- a/packages/inula-novdom/tests/For.test.tsx
+++ b/packages/inula-novdom/tests/For.test.tsx
@@ -22,7 +22,7 @@ import {
setAttribute as $$attr,
effect as $$effect,
} from '../src/dom';
-import { runComponent as $$runComponent, render as $$render } from '../src/core';
+import { runComponent as $$runComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$on } from '../src/event';
import { describe, expect } from 'vitest';
import { domTest as it } from './utils';
@@ -73,7 +73,7 @@ describe('For', () => {
* ;
* };
*
- * $$render(() =>
7 is between 5 and 10
7 is 7 or less
11 is greater than 10
XXX
YYY
ZZZ