@zhin.js/dependency 1.0.1

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 ADDED
@@ -0,0 +1,769 @@
1
+ # 🌲 @zhin.js/dependency
2
+
3
+ 一个强大的依赖树分析工具,支持动态导入、热重载、生命周期管理和可扩展的 Hook 系统。
4
+
5
+ ## 📋 目录
6
+
7
+ - [主要特性](#-主要特性)
8
+ - [安装](#-安装)
9
+ - [快速开始](#-快速开始)
10
+ - [基本用法](#基本用法)
11
+ - [在插件中使用 Hooks](#在插件中使用-hooks)
12
+ - [继承 Dependency 类](#继承-dependency-类)
13
+ - [配置](#-配置)
14
+ - [环境变量](#环境变量)
15
+ - [运行时配置](#运行时配置)
16
+ - [可扩展 Hook 系统](#-可扩展-hook-系统)
17
+ - [热重载](#-热重载)
18
+ - [类继承指南](#-类继承指南)
19
+ - [插件生态系统](#-插件生态系统)
20
+ - [API 文档](#-api-文档)
21
+ - [生命周期](#-生命周期)
22
+
23
+ ## ✨ 主要特性
24
+
25
+ - 🌲 **依赖树构建** - 自动构建模块依赖关系树
26
+ - 🔄 **热重载支持** - 文件变更时自动重载,保留子依赖树
27
+ - 🎯 **原生 import 支持** - 使用标准 ES 模块语法,无需自定义函数
28
+ - 🪝 **可扩展 Hook 系统** - 注册自定义 hooks,支持自动类型推断
29
+ - 📦 **跨运行时支持** - Node.js / tsx / Bun
30
+ - 🎨 **生命周期管理** - `start`, `mount`, `dispose`, `stop` 生命周期方法
31
+ - 🔔 **EventEmitter 集成** - 标准的事件系统
32
+ - 🎯 **TypeScript 类型支持** - 完整的类型定义和类型推断
33
+ - 🧬 **继承支持** - 完全支持类继承,创建自定义插件类
34
+
35
+ ## 📦 安装
36
+
37
+ ```bash
38
+ pnpm add @zhin.js/dependency
39
+ ```
40
+
41
+ ## 🚀 快速开始
42
+
43
+ ### 基本用法
44
+
45
+ ```typescript
46
+ import { Dependency } from '@zhin.js/dependency';
47
+
48
+ // 创建并启动依赖树
49
+ const root = new Dependency('./entry.js');
50
+ await root.start();
51
+
52
+ // 打印依赖树
53
+ console.log(root.printTree('', true, true));
54
+
55
+ // 停止依赖树
56
+ await root.stop();
57
+ ```
58
+
59
+ ### 在插件中使用 Hooks
60
+
61
+ ```typescript
62
+ // plugins/my-plugin.ts
63
+ import { onMount, onDispose, addListener } from '@zhin.js/dependency';
64
+
65
+ // 挂载钩子
66
+ onMount(() => {
67
+ console.log('插件已挂载!');
68
+ });
69
+
70
+ // 添加事件监听器
71
+ const unsubscribe = addListener('my-event', () => {
72
+ console.log('事件触发');
73
+ });
74
+
75
+ // 卸载钩子
76
+ onDispose(() => {
77
+ unsubscribe();
78
+ console.log('插件已卸载');
79
+ });
80
+
81
+ // 使用原生 import 导入子模块
82
+ import './child-plugin';
83
+
84
+ export default {};
85
+ ```
86
+
87
+ ### 继承 Dependency 类
88
+
89
+ 完全支持类继承,创建自定义插件类:
90
+
91
+ ```typescript
92
+ import { Dependency } from '@zhin.js/dependency';
93
+
94
+ class Plugin extends Dependency {
95
+ public version: string = '1.0.0';
96
+
97
+ constructor(filePath: string) {
98
+ super(filePath);
99
+ }
100
+
101
+ getInfo(): string {
102
+ return `${this.name} v${this.version}`;
103
+ }
104
+ }
105
+
106
+ // 使用自定义类
107
+ const root = new Plugin('./entry.js');
108
+ await root.start();
109
+
110
+ // 所有子节点也是 Plugin 实例!
111
+ console.log(root.children[0] instanceof Plugin); // true
112
+ console.log(root.children[0].getInfo()); // 可以使用自定义方法
113
+ ```
114
+
115
+ ## 🔧 配置
116
+
117
+ ### 环境变量
118
+
119
+ #### `DEPENDENCY_TREE_INCLUDE`
120
+
121
+ 指定需要处理的路径(优先级最高,即使在 `node_modules` 中也会处理)。
122
+
123
+ **使用场景:**
124
+
125
+ 1. **包含 npm 包中的插件** ⭐
126
+
127
+ ```bash
128
+ # 场景:你的插件发布为 npm 包,用户安装后需要被依赖树系统处理
129
+ DEPENDENCY_TREE_INCLUDE=node_modules/@my-org/my-plugin
130
+ ```
131
+
132
+ 2. **混合本地和 npm 插件**
133
+
134
+ ```bash
135
+ # 同时包含本地插件和多个 npm 包
136
+ DEPENDENCY_TREE_INCLUDE=src/plugins,node_modules/@org/plugin1,node_modules/@org/plugin2
137
+ ```
138
+
139
+ 3. **包含包内特定目录**
140
+
141
+ ```bash
142
+ # 只处理包内的 plugins 目录
143
+ DEPENDENCY_TREE_INCLUDE=node_modules/@my-org/my-plugin/plugins
144
+ ```
145
+
146
+ 4. **支持插件生态系统**(社区插件 + 官方插件)⭐
147
+
148
+ ```bash
149
+ # 同时支持社区插件 (zhin.js-*) 和官方插件 (@zhin.js/*)
150
+ DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-,node_modules/@zhin.js/
151
+ ```
152
+
153
+ #### `DEPENDENCY_TREE_EXCLUDE`
154
+
155
+ 指定需要排除的路径(优先级第二)。
156
+
157
+ ```bash
158
+ # 排除测试文件
159
+ DEPENDENCY_TREE_EXCLUDE=plugins/__tests__,plugins/**/*.test.ts
160
+ ```
161
+
162
+ ### 运行时配置
163
+
164
+ #### Bun
165
+
166
+ ```json
167
+ {
168
+ "scripts": {
169
+ "start": "bun --preload @zhin.js/dependency/bun-preload.ts src/index.ts"
170
+ }
171
+ }
172
+ ```
173
+
174
+ #### tsx
175
+
176
+ ```json
177
+ {
178
+ "scripts": {
179
+ "start": "tsx --import @zhin.js/dependency/register.mjs src/index.ts"
180
+ }
181
+ }
182
+ ```
183
+
184
+ #### Node.js(编译后)
185
+
186
+ ```json
187
+ {
188
+ "scripts": {
189
+ "build": "tsc",
190
+ "start": "node --import @zhin.js/dependency/register.mjs dist/index.js"
191
+ }
192
+ }
193
+ ```
194
+
195
+ ## 🪝 可扩展 Hook 系统
196
+
197
+ ### 自动类型推断
198
+
199
+ 通过 **Module Augmentation** 扩展 `Hooks` interface,实现自动类型推断:
200
+
201
+ ```typescript
202
+ import { registerHook, useHook } from '@zhin.js/dependency';
203
+
204
+ // 1️⃣ 扩展类型定义
205
+ declare module '@zhin.js/dependency' {
206
+ interface Hooks {
207
+ logger: (message: string, level?: 'info' | 'warn' | 'error') => void;
208
+ onBeforeMount: (callback: () => void) => void;
209
+ }
210
+ }
211
+
212
+ // 2️⃣ 注册 hook
213
+ registerHook({
214
+ name: 'logger',
215
+ handler: (dep, message, level = 'info') => {
216
+ console[level](`[${dep.name}] ${message}`);
217
+ }
218
+ });
219
+
220
+ // 3️⃣ 使用(类型自动推断!)
221
+ export const logger = useHook('logger'); // (message: string, level?: 'info' | 'warn' | 'error') => void
222
+
223
+ // ✅ TypeScript 提供完整的类型检查和智能提示
224
+ logger('Hello', 'info');
225
+ ```
226
+
227
+ ### 内置 Hooks
228
+
229
+ - `addListener(event, listener)` - 添加事件监听器
230
+ - `onMount(hook)` - 添加挂载钩子
231
+ - `onDispose(hook)` - 添加卸载钩子
232
+ - `importModule(path)` - 导入子模块
233
+
234
+ ### 自定义 Hooks API
235
+
236
+ - `registerHook(config)` - 注册自定义 hook
237
+ - `unregisterHook(name)` - 取消注册 hook
238
+ - `useHook(name)` - 创建 hook 函数(支持类型推断)
239
+ - `hasHook(name)` - 检查 hook 是否存在
240
+ - `getAllHooks()` - 获取所有已注册 hooks
241
+
242
+ ## 🔥 热重载
243
+
244
+ `Dependency` 提供了 `reload()` 方法来支持热重载。你可以使用 `chokidar` 监听文件变化,然后调用 `reload()` 来重新加载模块。
245
+
246
+ ### 基本示例
247
+
248
+ 使用**事件驱动**的方式动态收集文件路径:
249
+
250
+ ```typescript
251
+ import { Dependency } from '@zhin.js/dependency';
252
+ import chokidar from 'chokidar';
253
+
254
+ // 1. 创建依赖树和文件监听器
255
+ const root = new Dependency('./entry.js');
256
+ const watchedFiles = new Map<string, Dependency>();
257
+
258
+ // 2. 创建空的 watcher,准备动态添加文件
259
+ const watcher = chokidar.watch([], {
260
+ persistent: true,
261
+ ignoreInitial: true,
262
+ awaitWriteFinish: {
263
+ stabilityThreshold: 100,
264
+ pollInterval: 100
265
+ }
266
+ });
267
+
268
+ // 3. 监听 afterStart 事件,动态收集文件路径
269
+ root.on('afterStart', (dep: Dependency) => {
270
+ watchedFiles.set(dep.filePath, dep);
271
+ watcher.add(dep.filePath);
272
+ });
273
+
274
+ // 4. 启动依赖树(会触发 afterStart 事件)
275
+ await root.start();
276
+
277
+ // 5. 监听文件变化
278
+ watcher.on('change', async (changedPath: string) => {
279
+ const dep = watchedFiles.get(changedPath);
280
+ if (dep) {
281
+ console.log(`📝 文件变更: ${dep.name}`);
282
+ console.time('reload');
283
+
284
+ try {
285
+ const newDep = await dep.reload();
286
+ watchedFiles.set(newDep.filePath, newDep);
287
+ } catch (error) {
288
+ console.error(`❌ [${dep.name}] 重载失败:`, error);
289
+ }
290
+
291
+ console.timeEnd('reload');
292
+ }
293
+ });
294
+ ```
295
+
296
+ ### 热重载工作原理
297
+
298
+ 当调用 `dep.reload()` 时,会自动:
299
+
300
+ 1. **暂存子依赖** - 保存当前节点的 children
301
+ 2. **卸载当前节点** - 调用 `dispose()`
302
+ 3. **清除模块缓存** - 清除 require/import 缓存
303
+ 4. **重新导入** - 父节点重新 import 该文件(或根节点重新 start)
304
+ 5. **恢复子依赖** - 将暂存的 children 赋值给新节点
305
+ 6. **重新挂载** - 调用新节点的 `mount()`
306
+ 7. **返回新实例** - `reload()` 返回新的 `Dependency` 实例
307
+
308
+ ### 关键特性
309
+
310
+ - ✅ **支持根节点热重载** - 即使没有 parent 也能 reload
311
+ - ✅ **返回新实例** - `reload()` 返回 `Promise<Dependency>`
312
+ - ✅ **事件驱动** - 使用 `afterStart` 事件动态收集依赖
313
+ - ✅ **保留子树** - 子依赖会自动迁移到新实例
314
+ - ✅ **灵活可控** - 完全控制监听策略和重载时机
315
+
316
+ ### 优势
317
+
318
+ - 🚀 **性能优化** - 只监听实际需要的文件
319
+ - 🎯 **精确控制** - 可以根据需求定制监听策略
320
+ - 🔄 **增量更新** - 无需重新收集所有文件
321
+ - 💾 **内存友好** - 及时更新监听映射,避免内存泄漏
322
+ - 🛠️ **可扩展** - 可以结合其他工具(如 nodemon、pm2)
323
+
324
+ ## 🧬 类继承指南
325
+
326
+ ### 核心特性
327
+
328
+ - ✅ **完整继承支持** - 子节点自动使用父节点的类
329
+ - ✅ **类型安全** - 完整的 TypeScript 类型支持
330
+ - ✅ **生命周期保留** - 所有生命周期方法正常工作
331
+ - ✅ **热重载兼容** - 重载后的节点保持相同类型
332
+
333
+ ### 基本继承
334
+
335
+ ```typescript
336
+ import { Dependency } from '@zhin.js/dependency';
337
+
338
+ class Plugin extends Dependency {
339
+ public version: string = '1.0.0';
340
+ public author: string = 'unknown';
341
+
342
+ constructor(filePath: string) {
343
+ super(filePath);
344
+ }
345
+
346
+ // 添加自定义方法
347
+ getInfo(): string {
348
+ return `${this.name} v${this.version} by ${this.author}`;
349
+ }
350
+ }
351
+
352
+ // 使用自定义类
353
+ const root = new Plugin('./entry.js');
354
+ await root.start();
355
+
356
+ // 所有子节点也是 Plugin 实例!
357
+ console.log(root.children[0] instanceof Plugin); // true
358
+ ```
359
+
360
+ ### 实际示例
361
+
362
+ #### 示例 1:添加配置系统
363
+
364
+ ```typescript
365
+ interface PluginConfig {
366
+ enabled: boolean;
367
+ priority: number;
368
+ dependencies?: string[];
369
+ }
370
+
371
+ class ConfigurablePlugin extends Dependency {
372
+ private config: PluginConfig = {
373
+ enabled: true,
374
+ priority: 0
375
+ };
376
+
377
+ constructor(filePath: string, config?: Partial<PluginConfig>) {
378
+ super(filePath);
379
+ if (config) {
380
+ this.config = { ...this.config, ...config };
381
+ }
382
+ }
383
+
384
+ getConfig(): PluginConfig {
385
+ return { ...this.config };
386
+ }
387
+
388
+ updateConfig(config: Partial<PluginConfig>): void {
389
+ this.config = { ...this.config, ...config };
390
+ }
391
+
392
+ isEnabled(): boolean {
393
+ return this.config.enabled;
394
+ }
395
+ }
396
+ ```
397
+
398
+ #### 示例 2:添加性能监控
399
+
400
+ ```typescript
401
+ class MonitoredPlugin extends Dependency {
402
+ private metrics = {
403
+ loadTime: 0,
404
+ mountTime: 0,
405
+ childCount: 0
406
+ };
407
+
408
+ async start(): Promise<void> {
409
+ const startTime = Date.now();
410
+ await super.start();
411
+ this.metrics.loadTime = Date.now() - startTime;
412
+ }
413
+
414
+ async mount(): Promise<void> {
415
+ const startTime = Date.now();
416
+ await super.mount();
417
+ this.metrics.mountTime = Date.now() - startTime;
418
+ this.metrics.childCount = this.children.length;
419
+ }
420
+
421
+ getMetrics() {
422
+ return { ...this.metrics };
423
+ }
424
+
425
+ printMetrics(): void {
426
+ console.log(`📊 ${this.name} 性能指标:`);
427
+ console.log(` 加载时间: ${this.metrics.loadTime}ms`);
428
+ console.log(` 挂载时间: ${this.metrics.mountTime}ms`);
429
+ console.log(` 子节点数: ${this.metrics.childCount}`);
430
+ }
431
+ }
432
+ ```
433
+
434
+ ### 工作原理
435
+
436
+ 当父节点导入子模块时,`importChild()` 方法会自动使用 `this.constructor` 来创建子节点:
437
+
438
+ ```typescript
439
+ async importChild(importPath: string): Promise<Dependency> {
440
+ const absolutePath = this.resolveImportPath(this.#filePath, importPath);
441
+
442
+ // 使用父节点的构造函数创建子节点
443
+ const child = new (this.constructor as typeof Dependency)(absolutePath);
444
+
445
+ child.parent = this;
446
+ this.children.push(child);
447
+ await child.start();
448
+
449
+ return child;
450
+ }
451
+ ```
452
+
453
+ 这确保了:
454
+ - ✅ 子节点使用与父节点相同的类
455
+ - ✅ 整个依赖树保持类型一致
456
+ - ✅ 自定义属性和方法在所有节点上可用
457
+
458
+ ### 注意事项
459
+
460
+ #### 1. 构造函数参数
461
+
462
+ 如果你的自定义类需要额外的构造函数参数,需要确保只使用 `filePath` 作为必需参数:
463
+
464
+ ```typescript
465
+ // ✅ 正确:额外参数都是可选的
466
+ class MyPlugin extends Dependency {
467
+ constructor(filePath: string, config?: MyConfig) {
468
+ super(filePath);
469
+ // ...
470
+ }
471
+ }
472
+
473
+ // ❌ 错误:必需的额外参数会导致子节点创建失败
474
+ class MyPlugin extends Dependency {
475
+ constructor(filePath: string, config: MyConfig) { // config 是必需的
476
+ super(filePath);
477
+ // ...
478
+ }
479
+ }
480
+ ```
481
+
482
+ **解决方案:** 使用默认值或可选参数:
483
+
484
+ ```typescript
485
+ class MyPlugin extends Dependency {
486
+ constructor(
487
+ filePath: string,
488
+ config: MyConfig = { /* 默认值 */ }
489
+ ) {
490
+ super(filePath);
491
+ // ...
492
+ }
493
+ }
494
+ ```
495
+
496
+ #### 2. 异步初始化
497
+
498
+ 如果需要异步初始化,使用生命周期方法而不是构造函数:
499
+
500
+ ```typescript
501
+ class AsyncPlugin extends Dependency {
502
+ private initialized: boolean = false;
503
+
504
+ // ✅ 使用 start 方法
505
+ async start(): Promise<void> {
506
+ await this.initialize();
507
+ await super.start();
508
+ }
509
+
510
+ private async initialize(): Promise<void> {
511
+ // 异步初始化逻辑
512
+ this.initialized = true;
513
+ }
514
+ }
515
+ ```
516
+
517
+ ## 🔌 插件生态系统
518
+
519
+ ### 支持多种命名规范
520
+
521
+ #### 1. 社区插件(前缀命名)
522
+
523
+ ```
524
+ zhin.js-plugin1
525
+ zhin.js-my-plugin
526
+ zhin.js-awesome-feature
527
+ ```
528
+
529
+ #### 2. 官方插件(组织命名)
530
+
531
+ ```
532
+ @zhin.js/core
533
+ @zhin.js/plugin1
534
+ @zhin.js/database
535
+ ```
536
+
537
+ ### 配置方法
538
+
539
+ #### 方法 1:环境变量(推荐)
540
+
541
+ 在 `.env` 文件或启动脚本中设置:
542
+
543
+ ```bash
544
+ # 同时支持两种插件
545
+ DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-,node_modules/@zhin.js/
546
+ ```
547
+
548
+ #### 方法 2:package.json 脚本
549
+
550
+ ```json
551
+ {
552
+ "scripts": {
553
+ "dev": "DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-,node_modules/@zhin.js/ bun src/index.ts",
554
+ "start": "DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-,node_modules/@zhin.js/ tsx src/index.ts"
555
+ }
556
+ }
557
+ ```
558
+
559
+ #### 方法 3:使用 dotenv
560
+
561
+ ```bash
562
+ # .env
563
+ DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-,node_modules/@zhin.js/
564
+ ```
565
+
566
+ ```typescript
567
+ // index.ts
568
+ import 'dotenv/config';
569
+ import { Dependency } from '@zhin.js/dependency';
570
+
571
+ const root = new Dependency('./entry.js');
572
+ await root.start();
573
+ ```
574
+
575
+ ### 实际场景
576
+
577
+ #### 场景 1:纯官方插件生态
578
+
579
+ 如果你的项目只使用官方插件(如 `@zhin.js/*`):
580
+
581
+ ```bash
582
+ DEPENDENCY_TREE_INCLUDE=node_modules/@zhin.js/
583
+ ```
584
+
585
+ #### 场景 2:纯社区插件生态
586
+
587
+ 如果你的项目只使用社区插件(如 `zhin.js-*`):
588
+
589
+ ```bash
590
+ DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-
591
+ ```
592
+
593
+ #### 场景 3:混合生态 ⭐
594
+
595
+ 同时支持官方和社区插件(推荐):
596
+
597
+ ```bash
598
+ DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-,node_modules/@zhin.js/
599
+ ```
600
+
601
+ #### 场景 4:本地插件 + npm 插件
602
+
603
+ 同时支持本地开发和 npm 安装的插件:
604
+
605
+ ```bash
606
+ DEPENDENCY_TREE_INCLUDE=src/plugins,node_modules/zhin.js-,node_modules/@zhin.js/
607
+ ```
608
+
609
+ #### 场景 5:选择性包含
610
+
611
+ 只包含特定的插件:
612
+
613
+ ```bash
614
+ DEPENDENCY_TREE_INCLUDE=node_modules/@zhin.js/core,node_modules/zhin.js-auth,node_modules/zhin.js-database
615
+ ```
616
+
617
+ ### 排除特定插件
618
+
619
+ 使用 `DEPENDENCY_TREE_EXCLUDE` 排除不需要的插件:
620
+
621
+ ```bash
622
+ # 包含所有 zhin.js 插件,但排除测试和开发插件
623
+ DEPENDENCY_TREE_INCLUDE=node_modules/zhin.js-,node_modules/@zhin.js/
624
+ DEPENDENCY_TREE_EXCLUDE=node_modules/zhin.js-dev,node_modules/@zhin.js/testing
625
+ ```
626
+
627
+ ### 发布插件为 npm 包
628
+
629
+ #### 插件包作者(发布方)
630
+
631
+ 在你的插件包 README 中说明:
632
+
633
+ ```markdown
634
+ ## 使用方法
635
+
636
+ 安装插件:
637
+
638
+ \`\`\`bash
639
+ npm install @your-org/your-plugin
640
+ \`\`\`
641
+
642
+ 配置环境变量以启用依赖树转换:
643
+
644
+ \`\`\`bash
645
+ DEPENDENCY_TREE_INCLUDE=node_modules/@your-org/your-plugin
646
+ \`\`\`
647
+
648
+ 或者在 `package.json` 中:
649
+
650
+ \`\`\`json
651
+ {
652
+ "scripts": {
653
+ "start": "DEPENDENCY_TREE_INCLUDE=node_modules/@your-org/your-plugin tsx src/index.ts"
654
+ }
655
+ }
656
+ \`\`\`
657
+ ```
658
+
659
+ #### 插件使用者
660
+
661
+ ```bash
662
+ # .env 文件
663
+ DEPENDENCY_TREE_INCLUDE=node_modules/@my-org/plugin1,node_modules/@my-org/plugin2
664
+ ```
665
+
666
+ 或者在启动命令中:
667
+
668
+ ```json
669
+ {
670
+ "scripts": {
671
+ "start": "DEPENDENCY_TREE_INCLUDE=node_modules/@my-org/my-plugin tsx src/index.ts"
672
+ }
673
+ }
674
+ ```
675
+
676
+ ## 📚 API 文档
677
+
678
+ ### `Dependency` 类
679
+
680
+ #### 构造函数
681
+
682
+ ```typescript
683
+ new Dependency(filePath: string)
684
+ ```
685
+
686
+ #### 方法
687
+
688
+ - `async start()` - 启动依赖(导入模块并构建树)
689
+ - `async mount()` - 挂载(执行 onMount hooks)
690
+ - `async dispose()` - 卸载(执行 onDispose hooks)
691
+ - `async stop()` - 停止(dispose 并级联卸载子节点)
692
+ - `async reload(): Promise<Dependency>` - 热重载,返回新的 Dependency 实例(支持根节点)
693
+ - `printTree(prefix?, showListeners?, showPaths?)` - 打印树结构
694
+ - `toJSON()` - 导出为 JSON
695
+ - `dispatch(event, ...args)` - 触发当前节点的事件
696
+ - `broadcast(event, ...args)` - 广播事件到整个子树
697
+
698
+ #### 属性
699
+
700
+ - `name` - 依赖名称
701
+ - `filePath` - 文件路径
702
+ - `parent` - 父依赖
703
+ - `children` - 子依赖数组
704
+
705
+ #### 继承自 EventEmitter
706
+
707
+ ```typescript
708
+ // 监听事件
709
+ dep.on('afterMount', (dep) => console.log('挂载完成'));
710
+
711
+ // 触发事件
712
+ dep.emit('custom-event', data);
713
+
714
+ // 其他 EventEmitter 方法
715
+ dep.once(event, listener);
716
+ dep.off(event, listener);
717
+ dep.removeAllListeners(event);
718
+ ```
719
+
720
+ ## 🎨 生命周期
721
+
722
+ ```
723
+ ┌─────────────┐
724
+ │ create │ new Dependency()
725
+ └──────┬──────┘
726
+
727
+ ┌──────▼──────┐
728
+ │ start │ 导入模块,构建树
729
+ └──────┬──────┘
730
+
731
+ ┌──────▼──────┐
732
+ │ mount │ 执行 onMount hooks
733
+ └──────┬──────┘
734
+
735
+ ┌───▼────┐
736
+ │ active │ 运行中...
737
+ └───┬────┘
738
+
739
+ ┌──────▼──────┐
740
+ │ dispose │ 执行 onDispose hooks
741
+ └──────┬──────┘
742
+
743
+ ┌──────▼──────┐
744
+ │ stop │ 级联卸载子节点
745
+ └─────────────┘
746
+ ```
747
+
748
+ ### 生命周期事件
749
+
750
+ Dependency 类继承自 EventEmitter,在生命周期的各个阶段会触发相应事件:
751
+
752
+ - `beforeStart` - 开始启动前
753
+ - `afterStart` - 启动完成后
754
+ - `beforeMount` - 开始挂载前
755
+ - `afterMount` - 挂载完成后
756
+ - `beforeDispose` - 开始卸载前
757
+ - `afterDispose` - 卸载完成后
758
+ - `beforeReload` - 开始重载前
759
+ - `afterReload` - 重载完成后
760
+ - `fileChange` - 文件变更时
761
+ - `error` - 发生错误时
762
+
763
+ ## 🤝 贡献
764
+
765
+ 欢迎提交 Issue 和 Pull Request!
766
+
767
+ ## 📄 许可证
768
+
769
+ MIT