Skip to content

Commit 6af3d92

Browse files
committed
fix: fixed mapList
1 parent 7743b9e commit 6af3d92

File tree

5 files changed

+155
-55
lines changed

5 files changed

+155
-55
lines changed

packages/domily-playground/src/view/map-list/index.ts

Lines changed: 77 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,37 @@
1-
import { computed, reactive } from "domily";
1+
import { reactive, type Ref, ref } from "domily";
2+
3+
class Req implements Disposable {
4+
url: string;
5+
loading: Ref<boolean>;
6+
reqInit?: RequestInit;
7+
response?: Response;
8+
constructor(url: string, req?: RequestInit & { loading?: Ref<boolean> }) {
9+
const { loading, ...reqInit } = req || {};
10+
this.url = url;
11+
this.loading = loading || ref(false);
12+
this.reqInit = reqInit;
13+
loading.value = true;
14+
}
15+
16+
async fetch() {
17+
this.response = await fetch(this.url, this.reqInit);
18+
}
19+
20+
[Symbol.dispose]() {
21+
this.loading.value = false;
22+
}
23+
}
224

325
export default function MapList() {
26+
const loading = ref(false);
427
const state = reactive<{
5-
loading: boolean;
628
data: {
729
map: Map<string, any>;
830
array: string[];
931
set: Set<string>;
1032
};
1133
key: number;
1234
}>({
13-
loading: false,
1435
data: {
1536
map: new Map(),
1637
array: [],
@@ -31,35 +52,23 @@ export default function MapList() {
3152
});
3253

3354
const getData = async () => {
34-
state.loading = true;
35-
try {
36-
const rs = await fetch("https://api.pearktrue.cn/api/countdownday/");
37-
const json = (await rs.json()) as { data: string[] };
38-
style.color = "red";
39-
state.data.map = new Map(
40-
json.data.map((item, index) => [`${index}`, item])
41-
);
42-
state.data.set = new Set(json.data);
43-
state.data.array = json.data;
44-
} finally {
45-
state.loading = false;
46-
}
55+
await using req = new Req("https://api.pearktrue.cn/api/countdownday/", {
56+
loading,
57+
});
58+
await req.fetch();
59+
const json = (await req.response.json()) as { data: string[] };
60+
style.color = "red";
61+
state.data.map = new Map(
62+
json.data.map((item, index) => [`${index}`, item]),
63+
);
64+
state.data.set = new Set(json.data);
65+
state.data.array = json.data;
4766
};
4867

49-
const mapText = computed(() => {
50-
if (state.loading) {
51-
return "Loading...";
52-
}
53-
const data = Array.from(state.data.map.values());
54-
return JSON.stringify(data, null, 2);
55-
});
56-
57-
const setText = () => {
58-
if (state.loading) {
59-
return "Loading...";
60-
}
61-
const data = Array.from(state.data.set.values());
62-
return JSON.stringify(data, null, 2);
68+
const Loading = {
69+
tag: "div",
70+
domIf: () => loading.value,
71+
text: "Loading...",
6372
};
6473

6574
return {
@@ -92,7 +101,7 @@ export default function MapList() {
92101
click: () => {
93102
state.data.array.shift();
94103
state.data.map = new Map(
95-
state.data.array.map((item, index) => [`${index}`, item])
104+
state.data.array.map((item, index) => [`${index}`, item]),
96105
);
97106
state.data.set = new Set(state.data.array);
98107
},
@@ -107,7 +116,7 @@ export default function MapList() {
107116
const value = (Math.random() * 5000).toFixed(0) + "-" + Date.now();
108117
state.data.array.unshift(value);
109118
state.data.map = new Map(
110-
state.data.array.map((item, index) => [`${index}`, item])
119+
state.data.array.map((item, index) => [`${index}`, item]),
111120
);
112121
state.data.set = new Set(state.data.array);
113122
},
@@ -178,11 +187,27 @@ export default function MapList() {
178187
tag: "h3",
179188
text: "Map Data",
180189
},
190+
Loading,
181191
{
182192
tag: "div",
183193
style:
184194
'white-space: pre-wrap; font-family: "Courier New", Courier, monospace;',
185-
text: mapText,
195+
children: [
196+
{
197+
tag: "ul",
198+
domIf: () => !loading.value,
199+
mapList: {
200+
list: () => state.data.map,
201+
map: ([index, item]) => {
202+
return {
203+
tag: "li",
204+
key: `list-${index}`,
205+
text: item,
206+
};
207+
},
208+
},
209+
},
210+
],
186211
},
187212
],
188213
},
@@ -195,11 +220,27 @@ export default function MapList() {
195220
tag: "h3",
196221
text: "Set Data",
197222
},
223+
Loading,
198224
{
199225
tag: "div",
200226
style:
201227
'white-space: pre-wrap; font-family: "Courier New", Courier, monospace;',
202-
text: setText,
228+
children: [
229+
{
230+
tag: "ul",
231+
domIf: () => !loading.value,
232+
mapList: {
233+
list: () => state.data.set,
234+
map: (item: string, index: number) => {
235+
return {
236+
tag: "li",
237+
key: `list-${index}`,
238+
text: item,
239+
};
240+
},
241+
},
242+
},
243+
],
203244
},
204245
],
205246
},
@@ -212,14 +253,10 @@ export default function MapList() {
212253
tag: "h3",
213254
text: "Array Data",
214255
},
215-
{
216-
tag: "div",
217-
domIf: () => state.loading,
218-
text: "Loading...",
219-
},
256+
Loading,
220257
{
221258
tag: "ul",
222-
domIf: () => !state.loading,
259+
domIf: () => !loading.value,
223260
mapList: {
224261
list: () => state.data.array,
225262
map: (item: string, index: number) => {

packages/runtime-core/src/core/render/schema.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
txt,
2929
} from "../../utils/dom";
3030
import { hasDiff, merge } from "../../utils/obj";
31-
import { isFunction } from "../../utils/is";
31+
import { isFunction, isIterable } from "../../utils/is";
3232
import { domilyChildToDOM } from "./shared/parse";
3333
import DomilyFragment from "./custom-elements/fragment";
3434
import DomilyRouterView from "./custom-elements/router-view";
@@ -88,7 +88,7 @@ export default class DomilyRenderSchema<
8888
* list-loop
8989
*/
9090
mapList?: {
91-
list: WithFuncType<ListData[]>;
91+
list: WithFuncType<Iterable<ListData>>;
9292
map: (data: ListData, index: number) => DOMilyChild | DOMilyChildDOM;
9393
};
9494
key?: WithFuncType<string | number>;
@@ -417,7 +417,7 @@ export default class DomilyRenderSchema<
417417

418418
updateDOMList(
419419
map?: (data: ListData, index: number) => DOMilyChild | DOMilyChildDOM,
420-
list?: ListData[] | null
420+
list?: Iterable<ListData> | null
421421
) {
422422
if (!this.__dom || !handleWithFunType(this.domIf)) {
423423
return;
@@ -428,9 +428,10 @@ export default class DomilyRenderSchema<
428428
this.mappedSchemaList = [];
429429
this.mappedDOMList = [];
430430
const nextMappedListFragment = document.createDocumentFragment();
431-
if (Array.isArray(list) && isFunction(map)) {
432-
for (let i = 0; i < list.length; i++) {
433-
const child = map.apply(list, [list[i], i]);
431+
if (isIterable(list) && isFunction(map)) {
432+
let i = 0;
433+
for (const item of list) {
434+
const child = map.apply(list, [item, i++]);
434435
this.mappedSchemaList.push(child);
435436
const childDOM = domilyChildToDOM(
436437
child,
@@ -496,12 +497,10 @@ export default class DomilyRenderSchema<
496497
},
497498
this._internalEffectAborts
498499
);
499-
if (Array.isArray(previousList) && isFunction(this.mapList?.map)) {
500-
for (let i = 0; i < previousList.length; i++) {
501-
const child = this.mapList.map.apply(previousList, [
502-
previousList[i],
503-
i,
504-
]);
500+
if (isIterable(previousList) && isFunction(this.mapList?.map)) {
501+
let i = 0;
502+
for (const item of previousList) {
503+
const child = this.mapList.map.apply(previousList, [item, i++]);
505504
if (!this.mappedSchemaList) {
506505
this.mappedSchemaList = [child];
507506
} else {

packages/runtime-core/src/core/render/type/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ export interface IDomilyRenderOptions<
194194
* list-map
195195
*/
196196
mapList?: {
197-
list: WithFuncType<ListData[]>;
197+
list: WithFuncType<Iterable<ListData>>;
198198
map: (data: ListData, index: number) => DOMilyChild | DOMilyChildDOM;
199199
};
200200
key?: WithFuncType<string | number>;

packages/runtime-core/src/utils/is.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,9 @@ export const isThenable = (val: any): val is Thenable => {
2020
export const isES6Promise = (val: any): val is Promise<any> => {
2121
return isThenable(val) && val instanceof Promise;
2222
};
23+
24+
export const isIterable = (val: any): val is Iterable<any> => {
25+
return (
26+
isObject(val) && Symbol.iterator in val && isFunction(val[Symbol.iterator])
27+
);
28+
};

packages/runtime-core/src/utils/obj.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,16 @@ export const hasDiff = (
6363
_rv
6464
) => true
6565
): boolean => {
66+
/**
67+
* Someone may be a falsy value
68+
*/
6669
if ((!left && right) || (left && !right)) {
6770
return true;
6871
}
6972

73+
/**
74+
* Both are falsy value
75+
*/
7076
if (!left && !right) {
7177
return !Object.is(left, right);
7278
}
@@ -76,14 +82,24 @@ export const hasDiff = (
7682
const leftIsArray = Array.isArray(left);
7783
const rightIsArray = Array.isArray(right);
7884

85+
/**
86+
* The type is different
87+
*/
7988
if (leftType !== rightType) {
8089
return true;
8190
}
8291

92+
/**
93+
* The type is different
94+
* one of them is Array and another not be
95+
*/
8396
if ((leftIsArray && !rightIsArray) || (!leftIsArray && rightIsArray)) {
8497
return true;
8598
}
8699

100+
/**
101+
* Both are Array
102+
*/
87103
if (leftIsArray && rightIsArray) {
88104
if (left.length !== right.length) {
89105
return true;
@@ -92,8 +108,50 @@ export const hasDiff = (
92108
}
93109

94110
if (leftType === "object") {
95-
const leftKeys = Object.keys(left);
96-
const rightKeys = Object.keys(right);
111+
/**
112+
* The object type is different
113+
* one of them is iterable and another not be
114+
*/
115+
if (
116+
(Symbol.iterator in left && !(Symbol.iterator in right)) ||
117+
(!(Symbol.iterator in left) && Symbol.iterator in right)
118+
) {
119+
return true;
120+
}
121+
122+
/**
123+
* Both are iterator
124+
*/
125+
if (Symbol.iterator in left && Symbol.iterator in right) {
126+
const leftArray = [];
127+
const rightArray = [];
128+
for (const leftItem of left) {
129+
leftArray.push(leftItem);
130+
}
131+
for (const rightItem of right) {
132+
rightArray.push(rightItem);
133+
}
134+
return hasDiff(leftArray, rightArray, compare);
135+
}
136+
137+
/**
138+
* The one of them is Date
139+
* compare the result of its getTime()
140+
*/
141+
if (left instanceof Date) {
142+
return left.getTime() !== right.getTime?.();
143+
}
144+
145+
/**
146+
* The one of them is RegExp
147+
* compare theirs source and flags
148+
*/
149+
if (left instanceof RegExp) {
150+
return left.source !== right.source || left.flags !== right.flags;
151+
}
152+
153+
const leftKeys = Reflect.ownKeys(left);
154+
const rightKeys = Reflect.ownKeys(right);
97155
if (leftKeys.length !== rightKeys.length) {
98156
return true;
99157
}

0 commit comments

Comments
 (0)