@love-sqjm/magic 2026.4.15
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/LICENSE +674 -0
- package/README.md +93 -0
- package/app.js +51 -0
- package/doc/api/examples.md +563 -0
- package/doc/api/index.md +563 -0
- package/doc/architecture.md +322 -0
- package/doc/config-reference.md +646 -0
- package/doc/data-model.md +622 -0
- package/doc/development-guide.md +582 -0
- package/doc/magic-file/index.md +610 -0
- package/doc/user-guide/index.md +485 -0
- package/doc/workflow.md +548 -0
- package/index.js +157 -0
- package/magic.bat +2 -0
- package/magic.ps1 +5 -0
- package/package.json +44 -0
- package/script/build-project.js +16 -0
- package/script/config.js +23 -0
- package/script/create-project.js +73 -0
- package/script/global/printf.js +13 -0
- package/script/global/project-build-config.js +161 -0
- package/script/global/support-platform.js +5 -0
- package/script/module/compiler/global.js +43 -0
- package/script/module/compiler/id-generate.js +18 -0
- package/script/module/compiler/index-dom.js +78 -0
- package/script/module/compiler/macro-replace.js +22 -0
- package/script/module/compiler/macro.js +6 -0
- package/script/module/compiler/start.js +10 -0
- package/script/module/compiler/step/1.js +253 -0
- package/script/module/compiler/step/2.js +79 -0
- package/script/module/compiler/step/3.js +37 -0
- package/script/module/compiler/step/4.js +20 -0
- package/script/module/compiler/step/5.js +634 -0
- package/script/module/compiler/step/6.js +304 -0
- package/script/module/compiler/step/end.js +124 -0
- package/script/run-project.js +249 -0
- package/script/util/bun-fs.js +40 -0
- package/script/util/copy-dir.js +21 -0
- package/script/util/create-simple-dom-element.js +23 -0
- package/script/util/file-util.js +95 -0
- package/script/util/filtration-file.js +20 -0
- package/script/util/get-dir-all-file.js +28 -0
- package/script/util/get-first-object-key.js +9 -0
- package/script/util/is-empty-object.js +8 -0
- package/script/util/is-string-over-size.js +4 -0
- package/script/util/is.js +18 -0
- package/script/util/logging.js +142 -0
- package/script/util/task.js +16 -0
- package/script/util/traversal.js +28 -0
- package/template/platform-config/node-webkit +23 -0
- package/template/platform-config/web +1 -0
- package/template/project-base/app.xml +5 -0
- package/template/project-base/build.module.toml +37 -0
- package/template/project-base/build.toml +43 -0
- package/template/runtime/runtime.css +3 -0
- package/template/runtime/runtime.js +895 -0
package/doc/workflow.md
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
# Magic 业务流程文档
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
本文档描述 Magic 框架的核心业务流程,包括项目创建、编译构建、开发运行等关键环节。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. 项目创建流程
|
|
10
|
+
|
|
11
|
+
### 1.1 流程图
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
用户执行
|
|
15
|
+
│
|
|
16
|
+
▼
|
|
17
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
18
|
+
│ magic init [name] --web │
|
|
19
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
20
|
+
│
|
|
21
|
+
▼
|
|
22
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
23
|
+
│ createProject(name, "web") │
|
|
24
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
25
|
+
│ │ 1. 获取平台配置模板 (template/platform-config/web) │ │
|
|
26
|
+
│ │ 2. 读取项目基础模板 (template/project-base/build.toml) │ │
|
|
27
|
+
│ │ 3. 替换模板变量 ($name, $target, $config) │ │
|
|
28
|
+
│ │ 4. 创建目录结构 (name/app/) │ │
|
|
29
|
+
│ │ 5. 写入 build.toml 和 app/app.xml │ │
|
|
30
|
+
│ │ 6. 创建 app/index.m 入口文件 │ │
|
|
31
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
32
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
33
|
+
│
|
|
34
|
+
▼
|
|
35
|
+
项目创建完成
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 1.2 详细步骤
|
|
39
|
+
|
|
40
|
+
| 步骤 | 函数 | 说明 |
|
|
41
|
+
|------|------|------|
|
|
42
|
+
| 1 | `createProject(name, platform)` | 入口函数 |
|
|
43
|
+
| 2 | `app.templateDir.platformConfig.get(platform)` | 获取平台配置 |
|
|
44
|
+
| 3 | `app.templateDir.projectBase.get("build.toml")` | 获取项目模板 |
|
|
45
|
+
| 4 | 替换 `$name`, `$target`, `$config` | 填充配置 |
|
|
46
|
+
| 5 | `fs.mkdirSync()` | 创建目录 |
|
|
47
|
+
| 6 | `fs.writeFileSync()` | 写入配置文件 |
|
|
48
|
+
| 7 | 创建 `app/index.m` | 创建入口组件文件 |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 2. 项目构建流程
|
|
53
|
+
|
|
54
|
+
### 2.1 完整编译流水线
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
magic build
|
|
58
|
+
│
|
|
59
|
+
▼
|
|
60
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
61
|
+
│ BuildProject() │
|
|
62
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
63
|
+
│
|
|
64
|
+
▼
|
|
65
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
66
|
+
│ Step 1: 配置解析 │
|
|
67
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
68
|
+
│ │ examine_BuildConfig() │ │
|
|
69
|
+
│ │ 1. 加载 build.toml │ │
|
|
70
|
+
│ │ 2. 校验配置项类型和范围 │ │
|
|
71
|
+
│ │ 3. 解析 app.xml │ │
|
|
72
|
+
│ │ 4. 解析 import 标签 │ │
|
|
73
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
74
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
75
|
+
│
|
|
76
|
+
▼
|
|
77
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
78
|
+
│ Step 2: 文件扫描 │
|
|
79
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
80
|
+
│ │ _2(build_config, app_config) │ │
|
|
81
|
+
│ │ 1. 添加默认排除项 (app.xml, magic/) │ │
|
|
82
|
+
│ │ 2. filtrationFile() 扫描所有源文件 │ │
|
|
83
|
+
│ │ 3. 按扩展名分组创建 source 对象 │ │
|
|
84
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
85
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
86
|
+
│
|
|
87
|
+
▼
|
|
88
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
89
|
+
│ Step 3: 目录初始化 │
|
|
90
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
91
|
+
│ │ _3() │ │
|
|
92
|
+
│ │ 1. fs.rmSync() 清空输出目录 │ │
|
|
93
|
+
│ │ 2. fs.mkdirSync() 创建输出目录 │ │
|
|
94
|
+
│ │ 3. 复制 runtime.js 和 runtime.css │ │
|
|
95
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
96
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
97
|
+
│
|
|
98
|
+
▼
|
|
99
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
100
|
+
│ Step 4: 文件分类 │
|
|
101
|
+
│ ┌────────────────────────────────────────────────────────┘ │
|
|
102
|
+
│ │ _4() │ │
|
|
103
|
+
│ │ 1. 遍历所有源文件 │ │
|
|
104
|
+
│ │ 2. .m 文件收集到数组待处理 │ │
|
|
105
|
+
│ │ 3. 其他文件直接复制到输出目录 │ │
|
|
106
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
107
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
108
|
+
│
|
|
109
|
+
▼
|
|
110
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
111
|
+
│ Step 5: 核心编译 │
|
|
112
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
113
|
+
│ │ _5(m source[]) │ │
|
|
114
|
+
│ │ 1. 解析 import 标签 │ │
|
|
115
|
+
│ │ 2. 解析 template DOM 树 │ │
|
|
116
|
+
│ │ 3. 分类处理 script 标签 │ │
|
|
117
|
+
│ │ 4. 处理 css 标签和作用域 │ │
|
|
118
|
+
│ │ 5. 处理 expose-event │ │
|
|
119
|
+
│ │ 6. Babel AST 宏替换 │ │
|
|
120
|
+
│ │ 7. 生成 mData 对象数组 │ │
|
|
121
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
122
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
123
|
+
│
|
|
124
|
+
▼
|
|
125
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
126
|
+
│ Step 6: 代码生成 │
|
|
127
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
128
|
+
│ │ _6(mDatas, CSS_VAR) │ │
|
|
129
|
+
│ │ 1. 处理模块导入 │ │
|
|
130
|
+
│ │ 2. 创建 M*.js 和 M*.css 文件 │ │
|
|
131
|
+
│ │ 3. 更新 index_dom │ │
|
|
132
|
+
│ │ 4. debug/release 模式分别处理 │ │
|
|
133
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
134
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
135
|
+
│
|
|
136
|
+
▼
|
|
137
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
138
|
+
│ End: 压缩输出 │
|
|
139
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
140
|
+
│ │ _end(paths) │ │
|
|
141
|
+
│ │ 1. 生成 index.html │ │
|
|
142
|
+
│ │ 2. HTML/JS/CSS 压缩 │ │
|
|
143
|
+
│ │ 3. PostCSS Autoprefixer 处理 │ │
|
|
144
|
+
│ │ 4. 输出到 build/ 目录 │ │
|
|
145
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
146
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
147
|
+
│
|
|
148
|
+
▼
|
|
149
|
+
构建完成
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 3. Step 5 核心编译详解
|
|
155
|
+
|
|
156
|
+
### 3.1 .m 文件解析流程
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
.m 文件内容
|
|
160
|
+
│
|
|
161
|
+
▼
|
|
162
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
163
|
+
│ parse() 解析 DOM │
|
|
164
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
165
|
+
│
|
|
166
|
+
▼
|
|
167
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
168
|
+
│ 各标签并行处理 │
|
|
169
|
+
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|
170
|
+
│ │ <import> │ │<template>│ │ <script> │ │ <css> │ │
|
|
171
|
+
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
|
172
|
+
└───────┼─────────────┼─────────────┼─────────────┼────────────┘
|
|
173
|
+
│ │ │ │
|
|
174
|
+
▼ ▼ ▼ ▼
|
|
175
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
176
|
+
│ Babel AST 处理 │
|
|
177
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
178
|
+
│ │ 1. magic_define_include 宏替换 │ │
|
|
179
|
+
│ │ 2. magic_define_ui_data 转换 │ │
|
|
180
|
+
│ │ 3. magic_dynamic_value_bind 标记 │ │
|
|
181
|
+
│ │ 4. 提取事件/接口/监听函数 │ │
|
|
182
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
183
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
184
|
+
│
|
|
185
|
+
▼
|
|
186
|
+
mData 对象
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### 3.2 脚本分类处理
|
|
190
|
+
|
|
191
|
+
| code 属性 | 处理方式 | 存储位置 |
|
|
192
|
+
|-----------|----------|----------|
|
|
193
|
+
| 无 / `default` | 直接拼接 | `data.script` |
|
|
194
|
+
| `before` | 拼接后处理宏 | `data.before` |
|
|
195
|
+
| `global` | 拼接后处理宏 | `data.global` |
|
|
196
|
+
| `event` | 提取函数名,生成事件代码 | `data.event` |
|
|
197
|
+
| `listen` | 提取函数名,生成监听代码 | `data.listen` |
|
|
198
|
+
| `interface` | 提取函数名,生成接口代码 | `data.interface` |
|
|
199
|
+
|
|
200
|
+
### 3.3 CSS 处理流程
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
<css scope="#id:button" default-theme>
|
|
204
|
+
& {
|
|
205
|
+
background-color: #c6c6c6;
|
|
206
|
+
}
|
|
207
|
+
</css>
|
|
208
|
+
│
|
|
209
|
+
▼
|
|
210
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
211
|
+
│ 1. scope 属性解析 │
|
|
212
|
+
│ → 确定作用域选择器 │
|
|
213
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
214
|
+
│
|
|
215
|
+
▼
|
|
216
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
217
|
+
│ 2. 编译作用域选择器 │
|
|
218
|
+
│ → 生成唯一类名 .m-css-scope-abc123 │
|
|
219
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
220
|
+
│
|
|
221
|
+
▼
|
|
222
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
223
|
+
│ 3. default-theme 处理 (可选) │
|
|
224
|
+
│ → 将 CSS 值转换为 CSS 变量 │
|
|
225
|
+
│ → 添加到 CSS_VAR 字符串 │
|
|
226
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
227
|
+
│
|
|
228
|
+
▼
|
|
229
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
230
|
+
│ 4. 输出 │
|
|
231
|
+
│ CSS: .m-css-scope-abc123 { background-color: ... } │
|
|
232
|
+
│ VAR: --button-m-css-scope-abc123-background-color: ... │
|
|
233
|
+
└──────────────────────────────────────────────────────────────┘
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 4. 项目运行流程
|
|
239
|
+
|
|
240
|
+
### 4.1 Web 平台运行
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
magic run
|
|
244
|
+
│
|
|
245
|
+
▼
|
|
246
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
247
|
+
│ RunProject() │
|
|
248
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
249
|
+
│
|
|
250
|
+
▼
|
|
251
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
252
|
+
│ 1. 加载 build.toml │
|
|
253
|
+
│ 2. examine_BuildConfig() 校验配置 │
|
|
254
|
+
│ 3. 根据 platform.target 分发 │
|
|
255
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
256
|
+
│
|
|
257
|
+
▼
|
|
258
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
259
|
+
│ platform["web"](config) │
|
|
260
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
261
|
+
│ │ 判断运行模式: │ │
|
|
262
|
+
│ │ • browser: 启动浏览器 │ │
|
|
263
|
+
│ │ • server: 启动 HTTP 服务器 + WebSocket │ │
|
|
264
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
265
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
266
|
+
│
|
|
267
|
+
▼
|
|
268
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
269
|
+
│ HTTP 服务器 + WebSocket 热更新 │
|
|
270
|
+
│ ┌────────────────────────────────────────────────────────┐ │
|
|
271
|
+
│ │ 1. http.createServer() 创建 HTTP 服务器 │ │
|
|
272
|
+
│ │ 2. ws.Server() 创建 WebSocket 服务器 │ │
|
|
273
|
+
│ │ 3. 处理静态文件请求 │ │
|
|
274
|
+
│ │ 4. 广播刷新消息 │ │
|
|
275
|
+
│ │ 5. 客户端自动刷新页面 │ │
|
|
276
|
+
│ └────────────────────────────────────────────────────────┘ │
|
|
277
|
+
└──────────────────────────────────────────────────────────────┘
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### 4.2 热更新机制
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
284
|
+
│ 客户端 │ │ 服务器 │ │ 文件系统 │
|
|
285
|
+
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
|
286
|
+
│ │ │
|
|
287
|
+
│ WebSocket 连接 │ │
|
|
288
|
+
│───────────────────────>│ │
|
|
289
|
+
│ │ │
|
|
290
|
+
│ │ 每 500ms 轮询检查 │
|
|
291
|
+
│ │───────────────────────>│
|
|
292
|
+
│ │ │
|
|
293
|
+
│ │ 文件变化检测 │
|
|
294
|
+
│ │<───────────────────────│
|
|
295
|
+
│ │ │
|
|
296
|
+
│ 发送刷新指令 │ │
|
|
297
|
+
│<───────────────────────│ │
|
|
298
|
+
│ │ │
|
|
299
|
+
│ location.reload() │ │
|
|
300
|
+
│ 页面刷新 │ │
|
|
301
|
+
│ │ │
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## 5. 模块导入流程
|
|
307
|
+
|
|
308
|
+
### 5.1 导入解析
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
<import root="magic-ui/ui">
|
|
312
|
+
<module:control>
|
|
313
|
+
<list-view/>
|
|
314
|
+
</module:control>
|
|
315
|
+
</import>
|
|
316
|
+
│
|
|
317
|
+
▼
|
|
318
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
319
|
+
│ 解析 namespace │
|
|
320
|
+
│ "control" → namespace: "control" │
|
|
321
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
322
|
+
│
|
|
323
|
+
▼
|
|
324
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
325
|
+
│ 解析模块路径 │
|
|
326
|
+
│ module:list-view → magic-ui/ui/control/list-view │
|
|
327
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
328
|
+
│
|
|
329
|
+
▼
|
|
330
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
331
|
+
│ 生成导入映射 │
|
|
332
|
+
│ { │
|
|
333
|
+
│ "control": { │
|
|
334
|
+
│ "list-view": "magic-ui/ui/control/list-view" │
|
|
335
|
+
│ } │
|
|
336
|
+
│ } │
|
|
337
|
+
└──────────────────────────────────────────────────────────────┘
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### 5.2 运行时加载
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
magic.importM("list-view")
|
|
344
|
+
│
|
|
345
|
+
▼
|
|
346
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
347
|
+
│ 1. 名称标准化 │
|
|
348
|
+
│ name = "list-view".replace(/[^a-zA-Z]/g, '').toLowerCase()│
|
|
349
|
+
│ → "listview" │
|
|
350
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
351
|
+
│
|
|
352
|
+
▼
|
|
353
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
354
|
+
│ 2. 查找模块构造函数 │
|
|
355
|
+
│ window["__MAGIC__"]["M"]["listview"] │
|
|
356
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
357
|
+
│
|
|
358
|
+
▼
|
|
359
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
360
|
+
│ 3. 实例化 │
|
|
361
|
+
│ new window["__MAGIC__"]["M"]["listview"](args, listen) │
|
|
362
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
363
|
+
│
|
|
364
|
+
▼
|
|
365
|
+
返回模块元素
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## 6. 事件系统流程
|
|
371
|
+
|
|
372
|
+
### 6.1 事件定义与触发
|
|
373
|
+
|
|
374
|
+
```
|
|
375
|
+
【定义端】
|
|
376
|
+
<script code="event">
|
|
377
|
+
clickHandler = (event) => {
|
|
378
|
+
emit_event("click", { data: "test" });
|
|
379
|
+
}
|
|
380
|
+
</script>
|
|
381
|
+
│
|
|
382
|
+
▼
|
|
383
|
+
编译生成
|
|
384
|
+
│
|
|
385
|
+
▼
|
|
386
|
+
this.__magic_event = {
|
|
387
|
+
clickHandler: function(event) {...}
|
|
388
|
+
};
|
|
389
|
+
this.__magic_template.bind_event = () => {
|
|
390
|
+
magic.dom.event(element, "click", this, "clickHandler");
|
|
391
|
+
};
|
|
392
|
+
│
|
|
393
|
+
▼
|
|
394
|
+
emit_event = magic.emit.event(_listen);
|
|
395
|
+
│
|
|
396
|
+
▼
|
|
397
|
+
emit_event("click", { data: "test" });
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### 6.2 事件监听流程
|
|
401
|
+
|
|
402
|
+
```
|
|
403
|
+
【模板定义】
|
|
404
|
+
<child-component #listen:select="onSelect"/>
|
|
405
|
+
|
|
406
|
+
【编译后】
|
|
407
|
+
magic.importM("child-component", {}, {
|
|
408
|
+
select: (data) => this.__magic_listen_onSelect(data)
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
【监听函数】
|
|
412
|
+
<script code="listen">
|
|
413
|
+
onSelect = (data) => {
|
|
414
|
+
console.log("Selected:", data);
|
|
415
|
+
}
|
|
416
|
+
</script>
|
|
417
|
+
|
|
418
|
+
【触发流程】
|
|
419
|
+
子模块 emit_event("select", { value: "A" })
|
|
420
|
+
│
|
|
421
|
+
▼
|
|
422
|
+
调用 _listen["select"]({ value: "A" })
|
|
423
|
+
│
|
|
424
|
+
▼
|
|
425
|
+
执行 onSelect({ value: "A" })
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## 7. 响应式数据流
|
|
431
|
+
|
|
432
|
+
### 7.1 UiData 创建
|
|
433
|
+
|
|
434
|
+
```
|
|
435
|
+
const UiData = magic_define_ui_data({
|
|
436
|
+
text: "Hello",
|
|
437
|
+
count: 0
|
|
438
|
+
});
|
|
439
|
+
│
|
|
440
|
+
▼
|
|
441
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
442
|
+
│ 编译时转换 │
|
|
443
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
444
|
+
│
|
|
445
|
+
▼
|
|
446
|
+
const UiData = magic.createUiData({
|
|
447
|
+
text: "Hello",
|
|
448
|
+
count: 0
|
|
449
|
+
}, _args);
|
|
450
|
+
│
|
|
451
|
+
▼
|
|
452
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
453
|
+
│ createUiData() 返回深拷贝代理 │
|
|
454
|
+
│ • 支持类型转换 │
|
|
455
|
+
│ • 支持嵌套对象 │
|
|
456
|
+
│ • 返回响应式代理 │
|
|
457
|
+
└──────────────────────────────────────────────────────────────┘
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### 7.2 动态值绑定
|
|
461
|
+
|
|
462
|
+
```
|
|
463
|
+
magic_dynamic_value_bind($textElement)
|
|
464
|
+
│
|
|
465
|
+
▼
|
|
466
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
467
|
+
│ 编译时转换 │
|
|
468
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
469
|
+
│
|
|
470
|
+
▼
|
|
471
|
+
magic.DynamicValueBind($textElement, UiData);
|
|
472
|
+
│
|
|
473
|
+
▼
|
|
474
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
475
|
+
│ 运行时处理 │
|
|
476
|
+
│ 1. replaceMagicComments() 替换 ${} 为注释节点 │
|
|
477
|
+
│ 2. UiData.__DynamicValueBind() 绑定 │
|
|
478
|
+
│ 3. 当 UiData 属性变化时自动更新文本节点 │
|
|
479
|
+
└──────────────────────────────────────────────────────────────┘
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## 8. 编译错误处理流程
|
|
485
|
+
|
|
486
|
+
### 8.1 配置错误
|
|
487
|
+
|
|
488
|
+
```
|
|
489
|
+
examine_BuildConfig() 校验失败
|
|
490
|
+
│
|
|
491
|
+
▼
|
|
492
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
493
|
+
│ ProjectBuildConfigContrast() │
|
|
494
|
+
│ 发现类型不匹配或范围错误 │
|
|
495
|
+
└──────────────────────────┬───────────────────────────────────┘
|
|
496
|
+
│
|
|
497
|
+
▼
|
|
498
|
+
抛出错误: "目标 [key = value] 类型应该为 type"
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### 8.2 编译时错误
|
|
502
|
+
|
|
503
|
+
```
|
|
504
|
+
step/5.js Babel 解析失败
|
|
505
|
+
│
|
|
506
|
+
▼
|
|
507
|
+
┌──────────────────────────────────────────────────────────────┐
|
|
508
|
+
│ 抛出错误信息 │
|
|
509
|
+
│ code: <错误码> │
|
|
510
|
+
│ 错误原因: <reasonCode> │
|
|
511
|
+
│ 行 <line>, 列 <column> │
|
|
512
|
+
└──────────────────────────────────────────────────────────────┘
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## 9. 构建产物结构
|
|
518
|
+
|
|
519
|
+
### 9.1 Debug 模式
|
|
520
|
+
|
|
521
|
+
```
|
|
522
|
+
build/
|
|
523
|
+
├── index.html # 主页面
|
|
524
|
+
├── magic/
|
|
525
|
+
│ ├── runtime.js # 运行时
|
|
526
|
+
│ ├── runtime.css # 运行时样式
|
|
527
|
+
│ ├── default-theme-var.css # 主题变量
|
|
528
|
+
│ ├── 模块1.js # 每个模块独立文件
|
|
529
|
+
│ ├── 模块1.css
|
|
530
|
+
│ ├── 模块2.js
|
|
531
|
+
│ └── 模块2.css
|
|
532
|
+
├── 其他资源文件...
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### 9.2 Release 模式
|
|
536
|
+
|
|
537
|
+
```
|
|
538
|
+
build/
|
|
539
|
+
├── index.html # 压缩后的主页面
|
|
540
|
+
├── magic/
|
|
541
|
+
│ ├── runtime.js # 可能压缩
|
|
542
|
+
│ ├── runtime.css
|
|
543
|
+
│ ├── default-theme-var.css
|
|
544
|
+
│ ├── m.js # 合并的 JS(可能分块)
|
|
545
|
+
│ └── m-1.js # 超过 1MB 的分块
|
|
546
|
+
│ └── m-2.css # CSS 分块
|
|
547
|
+
├── 其他资源文件...
|
|
548
|
+
```
|