weifuwu 0.36.1 → 0.36.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -9
- package/dist/client/index.js +21 -12
- package/dist/client/vnode.d.ts +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -345,21 +345,28 @@ function Counter(_props: {}, ctx: WfuiContext) {
|
|
|
345
345
|
|
|
346
346
|
### 生命周期 —— ref 回调
|
|
347
347
|
|
|
348
|
+
`ref` 回调在 mount 时触发,接收 DOM 元素。返回的清理函数在 unmount 时由框架保证调用。
|
|
349
|
+
|
|
348
350
|
```tsx
|
|
349
351
|
function MyComponent(_props: {}, ctx: WfuiContext) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
// mount:
|
|
352
|
+
return (
|
|
353
|
+
<div ref={el => {
|
|
354
|
+
// mount: el 是 DOM 元素
|
|
353
355
|
el.addEventListener('scroll', handler)
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return <div ref={onRef} />
|
|
356
|
+
// 返回清理函数,unmount 时框架保证调用
|
|
357
|
+
return () => el.removeEventListener('scroll', handler)
|
|
358
|
+
}} />
|
|
359
|
+
)
|
|
360
360
|
}
|
|
361
361
|
```
|
|
362
362
|
|
|
363
|
+
| 场景 | 写法 |
|
|
364
|
+
|------|------|
|
|
365
|
+
| 事件监听 | `ref={el => { el.addEventListener(...); return () => el.removeEventListener(...) }}` |
|
|
366
|
+
| 定时器 | `ref={el => { const t = setInterval(f, 1000); return () => clearInterval(t) }}` |
|
|
367
|
+
| 第三方库 | `ref={el => { const c = new Chart(el); return () => c.destroy() }}` |
|
|
368
|
+
| 仅 mount | `ref={el => { init(el) }}` |
|
|
369
|
+
|
|
363
370
|
### 应用 —— createApp
|
|
364
371
|
|
|
365
372
|
```tsx
|
package/dist/client/index.js
CHANGED
|
@@ -56,7 +56,8 @@ function renderValue(v, ctx) {
|
|
|
56
56
|
el.appendChild(renderValue(child, ctx));
|
|
57
57
|
}
|
|
58
58
|
if (vnode.props?.ref) {
|
|
59
|
-
|
|
59
|
+
const result = vnode.props.ref(el);
|
|
60
|
+
if (typeof result === "function") vnode._cleanup = result;
|
|
60
61
|
}
|
|
61
62
|
return el;
|
|
62
63
|
}
|
|
@@ -140,7 +141,7 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
140
141
|
}
|
|
141
142
|
if (newInput == null) {
|
|
142
143
|
if (oldNode) {
|
|
143
|
-
|
|
144
|
+
callRefCleanup(oldInput);
|
|
144
145
|
oldNode.remove();
|
|
145
146
|
}
|
|
146
147
|
return null;
|
|
@@ -148,7 +149,7 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
148
149
|
const oldType = typeOf(oldInput);
|
|
149
150
|
const newType = typeOf(newInput);
|
|
150
151
|
if (oldType !== newType) {
|
|
151
|
-
|
|
152
|
+
callRefCleanup(oldInput);
|
|
152
153
|
const node = renderValue(newInput, ctx);
|
|
153
154
|
if (oldNode?.parentNode) {
|
|
154
155
|
oldNode.parentNode.replaceChild(node, oldNode);
|
|
@@ -181,7 +182,7 @@ function patchValue(parent, oldNode, oldInput, newInput, ctx) {
|
|
|
181
182
|
patchProps(oldNode, oldV.props, newV.props);
|
|
182
183
|
patchChildren(oldNode, oldV, newV, ctx);
|
|
183
184
|
} else if (oldNode) {
|
|
184
|
-
|
|
185
|
+
callRefCleanup(oldInput);
|
|
185
186
|
const node = renderValue(newInput, ctx);
|
|
186
187
|
oldNode.parentNode?.replaceChild(node, oldNode);
|
|
187
188
|
return node;
|
|
@@ -286,7 +287,7 @@ function patchSimpleChildren(parent, oldChildren, newChildren, ctx) {
|
|
|
286
287
|
parent.appendChild(node);
|
|
287
288
|
} else if (newChild === void 0) {
|
|
288
289
|
if (existingNode) {
|
|
289
|
-
|
|
290
|
+
callRefCleanup(oldChild);
|
|
290
291
|
existingNode.remove();
|
|
291
292
|
}
|
|
292
293
|
} else {
|
|
@@ -306,7 +307,7 @@ function patchKeyedChildren(parent, oldChildren, newChildren, ctx) {
|
|
|
306
307
|
for (const key of oldKeyMap.keys()) {
|
|
307
308
|
if (!newKeys.includes(key)) {
|
|
308
309
|
const entry = oldKeyMap.get(key);
|
|
309
|
-
|
|
310
|
+
callRefCleanup(entry.vnode);
|
|
310
311
|
entry.node?.remove();
|
|
311
312
|
oldKeyMap.delete(key);
|
|
312
313
|
}
|
|
@@ -316,7 +317,7 @@ function patchKeyedChildren(parent, oldChildren, newChildren, ctx) {
|
|
|
316
317
|
if (key === void 0) {
|
|
317
318
|
const node = parent.childNodes[i];
|
|
318
319
|
if (node) {
|
|
319
|
-
|
|
320
|
+
callRefCleanup(oldChildren[i]);
|
|
320
321
|
node.remove();
|
|
321
322
|
}
|
|
322
323
|
}
|
|
@@ -337,13 +338,21 @@ function patchKeyedChildren(parent, oldChildren, newChildren, ctx) {
|
|
|
337
338
|
}
|
|
338
339
|
}
|
|
339
340
|
}
|
|
340
|
-
function
|
|
341
|
+
function runRefCleanup(vnode) {
|
|
342
|
+
if (vnode._cleanup) {
|
|
343
|
+
vnode._cleanup();
|
|
344
|
+
vnode._cleanup = void 0;
|
|
345
|
+
}
|
|
346
|
+
forEach(vnode.props?.children, (child) => {
|
|
347
|
+
if (child && typeof child === "object" && child._cleanup) {
|
|
348
|
+
runRefCleanup(child);
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
function callRefCleanup(input) {
|
|
341
353
|
if (input == null || typeof input !== "object") return;
|
|
342
354
|
const vnode = input;
|
|
343
|
-
if (
|
|
344
|
-
vnode.props.ref(el);
|
|
345
|
-
}
|
|
346
|
-
forEach(vnode.props?.children, (child) => callRef(child, el));
|
|
355
|
+
if (vnode._cleanup) runRefCleanup(vnode);
|
|
347
356
|
}
|
|
348
357
|
|
|
349
358
|
// src/client/router.ts
|
package/dist/client/vnode.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ export interface VNode {
|
|
|
16
16
|
_$?: Record<string, any>;
|
|
17
17
|
/** 子 VNode 缓存(用于 patchValue diff,避免重复执行组件) */
|
|
18
18
|
_child?: any;
|
|
19
|
+
/** ref 回调返回的清理函数,卸载时由框架调用 */
|
|
20
|
+
_cleanup?: (() => void) | undefined;
|
|
19
21
|
}
|
|
20
22
|
export type Component<P = {}> = (props: P, ctx: WfuiContext) => VNode | null;
|
|
21
23
|
export declare const Fragment: unique symbol;
|