@lytjs/platform-adapter 6.4.0 → 6.5.0
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 +684 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
# @lytjs/platform-adapter
|
|
2
|
+
|
|
3
|
+
> LytJS 跨平台渲染适配器,提供统一的渲染器抽象层,支持多平台扩展。
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@lytjs/platform-adapter)
|
|
6
|
+
[](https://gitee.com/lytjs/lytjs/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
## 简介
|
|
9
|
+
|
|
10
|
+
`@lytjs/platform-adapter` 是 LytJS 框架的跨平台渲染适配器包,提供了一套统一的渲染器抽象接口,允许开发者为不同平台(Web、移动端、桌面端、服务端等)创建自定义渲染适配器。它实现了适配器注册表模式,支持插件扩展和运行时平台切换。
|
|
11
|
+
|
|
12
|
+
### 核心特性
|
|
13
|
+
|
|
14
|
+
- **统一抽象层**:为不同平台提供统一的渲染器接口
|
|
15
|
+
- **适配器注册表**:集中管理所有平台适配器
|
|
16
|
+
- **插件扩展系统**:支持通过插件扩展适配器功能
|
|
17
|
+
- **运行时切换**:支持在运行时动态切换平台
|
|
18
|
+
- **类型安全**:完整的 TypeScript 类型推导
|
|
19
|
+
- **零外部依赖**:完全基于原生 API 实现
|
|
20
|
+
- **可扩展架构**:易于添加新的平台支持
|
|
21
|
+
|
|
22
|
+
## 安装
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @lytjs/platform-adapter
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
或使用 pnpm:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pnpm add @lytjs/platform-adapter
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 依赖关系
|
|
35
|
+
|
|
36
|
+
`@lytjs/platform-adapter` 依赖以下 LytJS 核心包:
|
|
37
|
+
|
|
38
|
+
- `@lytjs/vdom` - 虚拟 DOM
|
|
39
|
+
- `@lytjs/common-vnode` - VNode 类型定义
|
|
40
|
+
- `@lytjs/common-is` - 工具函数
|
|
41
|
+
- `@lytjs/common-constants` - 常量定义
|
|
42
|
+
|
|
43
|
+
## 快速开始
|
|
44
|
+
|
|
45
|
+
### 创建渲染器
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
49
|
+
|
|
50
|
+
const renderer = createPlatformRenderer({
|
|
51
|
+
name: 'web',
|
|
52
|
+
platform: 'web',
|
|
53
|
+
createElement(type) {
|
|
54
|
+
return document.createElement(type);
|
|
55
|
+
},
|
|
56
|
+
insert(child, parent, anchor) {
|
|
57
|
+
parent.insertBefore(child, anchor);
|
|
58
|
+
},
|
|
59
|
+
remove(child, parent) {
|
|
60
|
+
parent.removeChild(child);
|
|
61
|
+
},
|
|
62
|
+
setElementText(el, text) {
|
|
63
|
+
el.textContent = text;
|
|
64
|
+
},
|
|
65
|
+
setElementAttribute(el, key, value) {
|
|
66
|
+
el.setAttribute(key, value);
|
|
67
|
+
},
|
|
68
|
+
createTextNode(text) {
|
|
69
|
+
return document.createTextNode(text);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 注册适配器
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
78
|
+
|
|
79
|
+
adapterRegistry.register('web', webRenderer);
|
|
80
|
+
adapterRegistry.register('ssr', ssrRenderer);
|
|
81
|
+
adapterRegistry.register('wechat', wechatRenderer);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 使用适配器
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
88
|
+
|
|
89
|
+
const renderer = adapterRegistry.get('web');
|
|
90
|
+
if (renderer) {
|
|
91
|
+
renderer.render(vnode, container);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 主要 API
|
|
96
|
+
|
|
97
|
+
### `createPlatformRenderer(config)`
|
|
98
|
+
|
|
99
|
+
创建平台渲染器。
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
103
|
+
|
|
104
|
+
const renderer = createPlatformRenderer({
|
|
105
|
+
name: 'my-platform',
|
|
106
|
+
platform: 'custom',
|
|
107
|
+
features: {
|
|
108
|
+
portals: true,
|
|
109
|
+
suspense: true,
|
|
110
|
+
errorBoundary: true
|
|
111
|
+
},
|
|
112
|
+
render(vnode, container) {
|
|
113
|
+
// 渲染逻辑
|
|
114
|
+
},
|
|
115
|
+
hydrate(vnode, container) {
|
|
116
|
+
// 水合逻辑
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `adapterRegistry`
|
|
122
|
+
|
|
123
|
+
适配器注册表,提供适配器的注册、获取和枚举功能。
|
|
124
|
+
|
|
125
|
+
#### `register(platform, adapter)`
|
|
126
|
+
|
|
127
|
+
注册平台适配器。
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
131
|
+
|
|
132
|
+
adapterRegistry.register('web', webRenderer);
|
|
133
|
+
adapterRegistry.register('miniapp', miniappRenderer);
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### `get(platform)`
|
|
137
|
+
|
|
138
|
+
获取指定平台的适配器。
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
142
|
+
|
|
143
|
+
const renderer = adapterRegistry.get('web');
|
|
144
|
+
if (renderer) {
|
|
145
|
+
renderer.render(vnode, container);
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### `has(platform)`
|
|
150
|
+
|
|
151
|
+
检查平台是否已注册。
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
155
|
+
|
|
156
|
+
if (adapterRegistry.has('web')) {
|
|
157
|
+
console.log('Web 平台已注册');
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### `unregister(platform)`
|
|
162
|
+
|
|
163
|
+
注销平台适配器。
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
167
|
+
|
|
168
|
+
adapterRegistry.unregister('web');
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
#### `list()`
|
|
172
|
+
|
|
173
|
+
列出所有已注册的适配器。
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
177
|
+
|
|
178
|
+
const platforms = adapterRegistry.list();
|
|
179
|
+
console.log('已注册的适配器:', platforms);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### `getDefault()`
|
|
183
|
+
|
|
184
|
+
获取默认平台适配器。
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
188
|
+
|
|
189
|
+
const defaultRenderer = adapterRegistry.getDefault();
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### `setDefault(platform)`
|
|
193
|
+
|
|
194
|
+
设置默认平台适配器。
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
198
|
+
|
|
199
|
+
adapterRegistry.setDefault('web');
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### `clear()`
|
|
203
|
+
|
|
204
|
+
清除所有注册的适配器。
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
208
|
+
|
|
209
|
+
adapterRegistry.clear();
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## 类型定义
|
|
213
|
+
|
|
214
|
+
### PlatformAdapter
|
|
215
|
+
|
|
216
|
+
平台适配器接口。
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
interface PlatformAdapter {
|
|
220
|
+
name: string;
|
|
221
|
+
platform: string;
|
|
222
|
+
features?: PlatformFeatures;
|
|
223
|
+
createElement(type: string, props?: VNodeProps): VNode;
|
|
224
|
+
insert(child: VNode, parent: VNode, anchor?: VNode): void;
|
|
225
|
+
remove(child: VNode, parent: VNode): void;
|
|
226
|
+
setElementText(el: VNode, text: string): void;
|
|
227
|
+
setElementAttribute(el: VNode, key: string, value: any): void;
|
|
228
|
+
removeElementAttribute(el: VNode, key: string): void;
|
|
229
|
+
createTextNode(text: string): VNode;
|
|
230
|
+
render(vnode: VNode, container: VNode): void;
|
|
231
|
+
hydrate?(vnode: VNode, container: VNode): void;
|
|
232
|
+
unmount?(vnode: VNode): void;
|
|
233
|
+
createPortal?(vnode: VNode, container: VNode): void;
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### PlatformConfig
|
|
238
|
+
|
|
239
|
+
平台配置选项。
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
interface PlatformConfig {
|
|
243
|
+
name: string;
|
|
244
|
+
platform: string;
|
|
245
|
+
features?: PlatformFeatures;
|
|
246
|
+
render: (vnode: VNode, container: VNode) => void;
|
|
247
|
+
hydrate?: (vnode: VNode, container: VNode) => void;
|
|
248
|
+
unmount?: (vnode: VNode) => void;
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### PlatformPlugin
|
|
253
|
+
|
|
254
|
+
平台插件接口。
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
interface PlatformPlugin {
|
|
258
|
+
name: string;
|
|
259
|
+
version: string;
|
|
260
|
+
install(platform: PlatformAdapter, options?: any): void;
|
|
261
|
+
uninstall?(platform: PlatformAdapter): void;
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### PlatformFeatures
|
|
266
|
+
|
|
267
|
+
平台特性支持。
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
interface PlatformFeatures {
|
|
271
|
+
portals?: boolean;
|
|
272
|
+
suspense?: boolean;
|
|
273
|
+
errorBoundary?: boolean;
|
|
274
|
+
transition?: boolean;
|
|
275
|
+
teleport?: boolean;
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 使用示例
|
|
280
|
+
|
|
281
|
+
### Web 平台适配器
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
285
|
+
|
|
286
|
+
const webRenderer = createPlatformRenderer({
|
|
287
|
+
name: 'web',
|
|
288
|
+
platform: 'web',
|
|
289
|
+
features: {
|
|
290
|
+
portals: true,
|
|
291
|
+
suspense: true,
|
|
292
|
+
errorBoundary: true,
|
|
293
|
+
transition: true,
|
|
294
|
+
teleport: true
|
|
295
|
+
},
|
|
296
|
+
|
|
297
|
+
createElement(type, props) {
|
|
298
|
+
const el = document.createElement(type);
|
|
299
|
+
if (props) {
|
|
300
|
+
Object.entries(props).forEach(([key, value]) => {
|
|
301
|
+
if (key.startsWith('on')) {
|
|
302
|
+
el.addEventListener(key.slice(2).toLowerCase(), value);
|
|
303
|
+
} else if (key === 'className') {
|
|
304
|
+
el.className = value;
|
|
305
|
+
} else {
|
|
306
|
+
el.setAttribute(key, value);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
return el;
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
insert(child, parent, anchor) {
|
|
314
|
+
parent.insertBefore(child, anchor || null);
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
remove(child, parent) {
|
|
318
|
+
parent.removeChild(child);
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
setElementText(el, text) {
|
|
322
|
+
el.textContent = text;
|
|
323
|
+
},
|
|
324
|
+
|
|
325
|
+
setElementAttribute(el, key, value) {
|
|
326
|
+
if (value === null || value === undefined) {
|
|
327
|
+
el.removeAttribute(key);
|
|
328
|
+
} else {
|
|
329
|
+
el.setAttribute(key, String(value));
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
removeElementAttribute(el, key) {
|
|
334
|
+
el.removeAttribute(key);
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
createTextNode(text) {
|
|
338
|
+
return document.createTextNode(text);
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
render(vnode, container) {
|
|
342
|
+
const el = this.createElement(vnode.type, vnode.props);
|
|
343
|
+
// 渲染逻辑
|
|
344
|
+
container.appendChild(el);
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
export default webRenderer;
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### 服务端渲染适配器
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
355
|
+
|
|
356
|
+
const ssrRenderer = createPlatformRenderer({
|
|
357
|
+
name: 'ssr',
|
|
358
|
+
platform: 'server',
|
|
359
|
+
features: {
|
|
360
|
+
portals: true,
|
|
361
|
+
suspense: true,
|
|
362
|
+
errorBoundary: true
|
|
363
|
+
},
|
|
364
|
+
|
|
365
|
+
createElement(type, props) {
|
|
366
|
+
return {
|
|
367
|
+
type,
|
|
368
|
+
props: props || {},
|
|
369
|
+
children: [],
|
|
370
|
+
text: ''
|
|
371
|
+
};
|
|
372
|
+
},
|
|
373
|
+
|
|
374
|
+
insert(child, parent) {
|
|
375
|
+
child.parent = parent;
|
|
376
|
+
parent.children = parent.children || [];
|
|
377
|
+
parent.children.push(child);
|
|
378
|
+
},
|
|
379
|
+
|
|
380
|
+
setElementText(el, text) {
|
|
381
|
+
el.text = text;
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
render(vnode, container) {
|
|
385
|
+
const html = this.stringify(vnode);
|
|
386
|
+
return html;
|
|
387
|
+
},
|
|
388
|
+
|
|
389
|
+
stringify(node) {
|
|
390
|
+
if (node.text) {
|
|
391
|
+
return node.text;
|
|
392
|
+
}
|
|
393
|
+
const children = (node.children || [])
|
|
394
|
+
.map(child => this.stringify(child))
|
|
395
|
+
.join('');
|
|
396
|
+
return `<${node.type}>${children}</${node.type}>`;
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
export default ssrRenderer;
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### 微信小程序适配器
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
407
|
+
|
|
408
|
+
const miniappRenderer = createPlatformRenderer({
|
|
409
|
+
name: 'wechat-miniapp',
|
|
410
|
+
platform: 'miniapp',
|
|
411
|
+
features: {
|
|
412
|
+
portals: false,
|
|
413
|
+
suspense: false,
|
|
414
|
+
errorBoundary: false
|
|
415
|
+
},
|
|
416
|
+
|
|
417
|
+
createElement(type, props) {
|
|
418
|
+
return {
|
|
419
|
+
type,
|
|
420
|
+
props: props || {},
|
|
421
|
+
children: []
|
|
422
|
+
};
|
|
423
|
+
},
|
|
424
|
+
|
|
425
|
+
render(vnode, container) {
|
|
426
|
+
const data = this.flatten(vnode);
|
|
427
|
+
container.setData({ elements: data });
|
|
428
|
+
},
|
|
429
|
+
|
|
430
|
+
flatten(node, depth = 0) {
|
|
431
|
+
return {
|
|
432
|
+
tag: node.type,
|
|
433
|
+
attrs: node.props,
|
|
434
|
+
children: (node.children || []).map(child =>
|
|
435
|
+
this.flatten(child, depth + 1)
|
|
436
|
+
)
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
export default miniappRenderer;
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### 使用插件扩展
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import { adapterRegistry, createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
448
|
+
|
|
449
|
+
const loggerPlugin = {
|
|
450
|
+
name: 'logger-plugin',
|
|
451
|
+
version: '1.0.0',
|
|
452
|
+
install(platform) {
|
|
453
|
+
const originalRender = platform.render;
|
|
454
|
+
platform.render = (vnode, container) => {
|
|
455
|
+
console.log(`[${platform.name}] 开始渲染`);
|
|
456
|
+
const start = performance.now();
|
|
457
|
+
originalRender.call(platform, vnode, container);
|
|
458
|
+
console.log(`[${platform.name}] 渲染完成,耗时: ${performance.now() - start}ms`);
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const webRenderer = createPlatformRenderer({ /* ... */ });
|
|
464
|
+
webRenderer.use?.(loggerPlugin);
|
|
465
|
+
|
|
466
|
+
adapterRegistry.register('web', webRenderer);
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### 运行时平台切换
|
|
470
|
+
|
|
471
|
+
```typescript
|
|
472
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
473
|
+
|
|
474
|
+
function renderApp(vnode) {
|
|
475
|
+
const platform = getPlatformFromUA();
|
|
476
|
+
const renderer = adapterRegistry.get(platform);
|
|
477
|
+
|
|
478
|
+
if (!renderer) {
|
|
479
|
+
console.warn(`平台 ${platform} 未注册,使用默认渲染器`);
|
|
480
|
+
return adapterRegistry.getDefault()?.render(vnode, container);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return renderer.render(vnode, container);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function getPlatformFromUA() {
|
|
487
|
+
const ua = navigator.userAgent;
|
|
488
|
+
if (ua.includes('MiniProgram')) return 'wechat';
|
|
489
|
+
return 'web';
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
### 动态加载适配器
|
|
494
|
+
|
|
495
|
+
```typescript
|
|
496
|
+
import { adapterRegistry } from '@lytjs/platform-adapter';
|
|
497
|
+
|
|
498
|
+
async function loadPlatformAdapter(platform) {
|
|
499
|
+
const modules = {
|
|
500
|
+
web: () => import('./adapters/web'),
|
|
501
|
+
ssr: () => import('./adapters/ssr'),
|
|
502
|
+
miniapp: () => import('./adapters/miniapp')
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
if (modules[platform]) {
|
|
506
|
+
const { default: adapter } = await modules[platform]();
|
|
507
|
+
adapterRegistry.register(platform, adapter);
|
|
508
|
+
return adapter;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
throw new Error(`未知的平台: ${platform}`);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
await loadPlatformAdapter('web');
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## 高级用法
|
|
518
|
+
|
|
519
|
+
### 自定义渲染流水线
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
523
|
+
|
|
524
|
+
const pipelineRenderer = createPlatformRenderer({
|
|
525
|
+
name: 'pipeline',
|
|
526
|
+
platform: 'custom',
|
|
527
|
+
features: {
|
|
528
|
+
portals: true,
|
|
529
|
+
suspense: true,
|
|
530
|
+
errorBoundary: true
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
render(vnode, container) {
|
|
534
|
+
const pipeline = [
|
|
535
|
+
this.optimize,
|
|
536
|
+
this.transform,
|
|
537
|
+
this.render
|
|
538
|
+
];
|
|
539
|
+
|
|
540
|
+
let current = vnode;
|
|
541
|
+
for (const step of pipeline) {
|
|
542
|
+
current = step.call(this, current);
|
|
543
|
+
}
|
|
544
|
+
return current;
|
|
545
|
+
},
|
|
546
|
+
|
|
547
|
+
optimize(vnode) {
|
|
548
|
+
// 优化阶段
|
|
549
|
+
return vnode;
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
transform(vnode) {
|
|
553
|
+
// 转换阶段
|
|
554
|
+
return vnode;
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### 性能监控适配器
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
563
|
+
|
|
564
|
+
function createMonitoredRenderer(config) {
|
|
565
|
+
const renderer = createPlatformRenderer(config);
|
|
566
|
+
|
|
567
|
+
const metrics = {
|
|
568
|
+
renderCount: 0,
|
|
569
|
+
totalTime: 0
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const originalRender = renderer.render;
|
|
573
|
+
renderer.render = function(vnode, container) {
|
|
574
|
+
const start = performance.now();
|
|
575
|
+
originalRender.call(this, vnode, container);
|
|
576
|
+
metrics.renderCount++;
|
|
577
|
+
metrics.totalTime += performance.now() - start;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
renderer.getMetrics = () => ({ ...metrics });
|
|
581
|
+
|
|
582
|
+
return renderer;
|
|
583
|
+
}
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### 调试适配器
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
590
|
+
|
|
591
|
+
const debugRenderer = createPlatformRenderer({
|
|
592
|
+
name: 'debug',
|
|
593
|
+
platform: 'web',
|
|
594
|
+
// ... 基础配置
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
debugRenderer.debug = {
|
|
598
|
+
logVNode(vnode) {
|
|
599
|
+
console.log('VNode:', JSON.stringify(vnode, null, 2));
|
|
600
|
+
},
|
|
601
|
+
logTree(vnode, depth = 0) {
|
|
602
|
+
const indent = ' '.repeat(depth);
|
|
603
|
+
console.log(`${indent}${vnode.type}`);
|
|
604
|
+
(vnode.children || []).forEach(child =>
|
|
605
|
+
this.logTree(child, depth + 1)
|
|
606
|
+
);
|
|
607
|
+
},
|
|
608
|
+
logOperations(operations) {
|
|
609
|
+
console.table(operations);
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
## 最佳实践
|
|
615
|
+
|
|
616
|
+
### 适配器命名规范
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
// ✅ 推荐:使用平台标识符
|
|
620
|
+
adapterRegistry.register('web', webRenderer);
|
|
621
|
+
adapterRegistry.register('ssr', ssrRenderer);
|
|
622
|
+
adapterRegistry.register('wechat-miniapp', wechatRenderer);
|
|
623
|
+
adapterRegistry.register('alipay-miniapp', alipayRenderer);
|
|
624
|
+
|
|
625
|
+
// ❌ 避免:使用模糊名称
|
|
626
|
+
adapterRegistry.register('main', webRenderer);
|
|
627
|
+
adapterRegistry.register('alt', ssrRenderer);
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### 特性检测
|
|
631
|
+
|
|
632
|
+
```typescript
|
|
633
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
634
|
+
|
|
635
|
+
const renderer = createPlatformRenderer({
|
|
636
|
+
name: 'adaptive',
|
|
637
|
+
platform: 'web',
|
|
638
|
+
|
|
639
|
+
features: {
|
|
640
|
+
portals: typeof document.createElement === 'function',
|
|
641
|
+
suspense: 'requestIdleCallback' in window,
|
|
642
|
+
errorBoundary: true
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### 错误处理
|
|
648
|
+
|
|
649
|
+
```typescript
|
|
650
|
+
import { createPlatformRenderer } from '@lytjs/platform-adapter';
|
|
651
|
+
|
|
652
|
+
const safeRenderer = createPlatformRenderer({
|
|
653
|
+
name: 'safe',
|
|
654
|
+
platform: 'web',
|
|
655
|
+
|
|
656
|
+
render(vnode, container) {
|
|
657
|
+
try {
|
|
658
|
+
// 渲染逻辑
|
|
659
|
+
} catch (error) {
|
|
660
|
+
console.error('渲染错误:', error);
|
|
661
|
+
this.handleError?.(error, vnode);
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
|
|
665
|
+
handleError(error, vnode) {
|
|
666
|
+
// 显示错误边界
|
|
667
|
+
}
|
|
668
|
+
});
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
## 浏览器兼容性
|
|
672
|
+
|
|
673
|
+
`@lytjs/platform-adapter` 支持所有现代浏览器。不同平台的适配器可能有特定的浏览器要求。
|
|
674
|
+
|
|
675
|
+
## 许可证
|
|
676
|
+
|
|
677
|
+
MIT License - [查看许可证](https://gitee.com/lytjs/lytjs/blob/main/LICENSE)
|
|
678
|
+
|
|
679
|
+
## 贡献指南
|
|
680
|
+
|
|
681
|
+
欢迎提交 Issue 和 Pull Request!
|
|
682
|
+
|
|
683
|
+
- [Gitee 仓库](https://gitee.com/lytjs/lytjs)
|
|
684
|
+
- [问题反馈](https://gitee.com/lytjs/lytjs/issues)
|