@hd-front-end/jsbridge-sdk 1.0.2 → 1.0.4
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 +4 -2
- package/dist/index.d.ts +201 -2
- package/dist/index.esm.js +444 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +446 -0
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +446 -0
- package/dist/index.umd.js.map +1 -1
- package/docs/00-/351/241/271/347/233/256/346/246/202/350/247/210.md +282 -0
- package/docs/01-/346/236/266/346/236/204/350/256/276/350/256/241.md +623 -0
- package/docs/02-/346/212/200/346/234/257/345/256/236/347/216/260.md +867 -0
- package/docs/03-API/344/275/277/347/224/250/346/226/207/346/241/243.md +1104 -0
- package/docs/04-/346/265/213/350/257/225/346/226/271/346/241/210.md +360 -0
- package/docs/05-/350/277/201/347/247/273/346/214/207/345/215/227.md +181 -0
- package/docs/06-/346/236/266/346/236/204/345/233/276/351/233/206.md +738 -0
- package/docs/07-/346/226/260/346/241/245/346/216/245/346/226/271/346/263/225/346/211/251/345/261/225/350/257/264/346/230/216.md +139 -0
- package/docs/CODE_REVIEW.md +65 -0
- package/docs/EVALUATION.md +72 -0
- package/docs/README.md +258 -0
- package/docs//345/205/263/351/224/256/351/227/256/351/242/230/350/247/243/347/255/224.md +495 -0
- package/docs//346/226/207/346/241/243/346/225/264/345/220/210/350/257/264/346/230/216.md +265 -0
- package/docs//346/233/264/346/226/260/346/227/245/345/277/227.md +669 -0
- package/docs//347/224/237/344/272/247/347/272/247-/345/277/253/351/200/237/345/274/200/345/247/213-v2.md +673 -0
- package/docs//347/224/237/344/272/247/347/272/247-/346/236/266/346/236/204/350/256/276/350/256/241-v2.md +730 -0
- package/docs//350/256/276/350/256/241/347/220/206/345/277/265/350/257/264/346/230/216.md +438 -0
- package/package.json +3 -2
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
# JSBridge SDK 关键问题解答
|
|
2
|
+
|
|
3
|
+
## 问题来源
|
|
4
|
+
|
|
5
|
+
在设计 JSBridge SDK 时,你提出了两个非常关键的问题:
|
|
6
|
+
|
|
7
|
+
1. **当前 SDK 几乎全部为 JS 逻辑,为什么会有技术栈的差别?**
|
|
8
|
+
2. **在应用引入过程中采用了 hdAppAdapter.ts 和 uni-app-api.json 适配器的逻辑,架构中没体现?**
|
|
9
|
+
|
|
10
|
+
这两个问题直接指出了原设计的重大疏漏!
|
|
11
|
+
|
|
12
|
+
## 🎯 问题 1:为什么会有技术栈差别?
|
|
13
|
+
|
|
14
|
+
### 疑问分析
|
|
15
|
+
|
|
16
|
+
看起来 JSBridge 都是 JavaScript 代码,理论上应该在 Vue2、Vue3、React 中都一样工作,为什么还要区分技术栈?
|
|
17
|
+
|
|
18
|
+
### 根本原因
|
|
19
|
+
|
|
20
|
+
**差别不在 JSBridge 通信本身,而在与 uni-app 的集成方式!**
|
|
21
|
+
|
|
22
|
+
具体来说,问题出在 **uni 对象的属性定义**上:
|
|
23
|
+
|
|
24
|
+
#### Vue2 项目(SOA)
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
// uni 对象的属性是可写的
|
|
28
|
+
uni.scanCode = function() { ... } // ✅ 成功
|
|
29
|
+
|
|
30
|
+
// 原因:uni-app Vue2 版本的实现
|
|
31
|
+
Object.defineProperty(uni, 'scanCode', {
|
|
32
|
+
value: originalScanCode,
|
|
33
|
+
writable: true, // ← 可写!
|
|
34
|
+
configurable: true
|
|
35
|
+
})
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Vue3 项目(MPA-Mini-V3)
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// uni 对象的某些属性是只读的
|
|
42
|
+
uni.chooseImage = function() { ... }
|
|
43
|
+
// ❌ Error: Cannot assign to read only property 'chooseImage'
|
|
44
|
+
|
|
45
|
+
// 原因:uni-app Vue3 版本的实现
|
|
46
|
+
Object.defineProperty(uni, 'chooseImage', {
|
|
47
|
+
value: originalChooseImage,
|
|
48
|
+
writable: false, // ← 只读!
|
|
49
|
+
configurable: false
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 实际代码证据
|
|
54
|
+
|
|
55
|
+
从你提供的代码中可以看到:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// context/mpa-mini-v3/src/h5Adapter/UniProxy.ts
|
|
59
|
+
// 为什么会有这个类?
|
|
60
|
+
// uni.chooseImage = chooseImage
|
|
61
|
+
// Cannot assign to read only property 'chooseImage' of object '[object Object]'
|
|
62
|
+
// chooseImage 是只读的,无法替换,只能用代理模式
|
|
63
|
+
|
|
64
|
+
export const UniProxy = {
|
|
65
|
+
chooseImage: uni.chooseImage,
|
|
66
|
+
pathToBase64: () => {}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// context/soa/src/h5Adapter/hdAppAdapter.ts (Vue2 项目)
|
|
72
|
+
// 可以直接赋值
|
|
73
|
+
uni.scanCode = (options: UniApp.ScanCodeOptions) => { ... } // ✅ OK
|
|
74
|
+
|
|
75
|
+
// 但 chooseImage 也用了 UniProxy
|
|
76
|
+
UniProxy.chooseImage = (options: UniApp.ChooseImageOptions) => { ... }
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### 技术栈差别总结
|
|
80
|
+
|
|
81
|
+
| 项目 | Vue 版本 | uni API 可写性 | 解决方案 |
|
|
82
|
+
|------|---------|---------------|---------|
|
|
83
|
+
| SOA | Vue2 | 大部分可写 | 直接赋值 |
|
|
84
|
+
| MPA-Mini-V3 | Vue3 | 部分只读 | UniProxy 代理 |
|
|
85
|
+
|
|
86
|
+
### 通用解决方案
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// 兼容 Vue2 和 Vue3 的写法
|
|
90
|
+
function overrideUniAPI(apiName: string, handler: Function) {
|
|
91
|
+
try {
|
|
92
|
+
// 尝试直接赋值(Vue2)
|
|
93
|
+
uni[apiName] = handler
|
|
94
|
+
console.log(`${apiName} 直接赋值成功`)
|
|
95
|
+
} catch (error) {
|
|
96
|
+
// 失败则使用 UniProxy(Vue3)
|
|
97
|
+
console.warn(`${apiName} 只读,使用 UniProxy`)
|
|
98
|
+
if (window.UniProxy) {
|
|
99
|
+
window.UniProxy[apiName] = handler
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## 🏗️ 问题 2:hdAppAdapter 在架构中的位置?
|
|
106
|
+
|
|
107
|
+
### 疑问分析
|
|
108
|
+
|
|
109
|
+
现有项目中有 `hdAppAdapter.ts` 和 `uni-app-api.json`,它们的作用是什么?在架构设计中为什么没有体现?
|
|
110
|
+
|
|
111
|
+
### hdAppAdapter 的关键作用
|
|
112
|
+
|
|
113
|
+
**它是一个 uni API 拦截适配层,让业务代码无需修改!**
|
|
114
|
+
|
|
115
|
+
#### 没有适配层的问题
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// ❌ 业务代码需要大量修改
|
|
119
|
+
// 旧代码
|
|
120
|
+
uni.scanCode({
|
|
121
|
+
success: (res) => {
|
|
122
|
+
console.log(res.result)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
// 需要改成
|
|
127
|
+
import { JSBridge } from '@hd-front-end/jsbridge-sdk'
|
|
128
|
+
|
|
129
|
+
JSBridge.scan({
|
|
130
|
+
scanType: ['qrCode'],
|
|
131
|
+
hideAlbum: false,
|
|
132
|
+
// ... 很多参数
|
|
133
|
+
}).then((result) => {
|
|
134
|
+
if (result.resp_code === 1000) {
|
|
135
|
+
console.log(result.resp_result)
|
|
136
|
+
}
|
|
137
|
+
})
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
#### 有适配层的优势
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// ✅ 业务代码完全不用改!
|
|
144
|
+
uni.scanCode({
|
|
145
|
+
success: (res) => {
|
|
146
|
+
console.log(res.result)
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// hdAppAdapter 在背后做了:
|
|
151
|
+
// 1. 拦截 uni.scanCode 调用
|
|
152
|
+
// 2. 转换参数格式
|
|
153
|
+
// 3. 调用 JSBridge
|
|
154
|
+
// 4. 转换返回结果
|
|
155
|
+
// 5. 调用 success 回调
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### hdAppAdapter 的工作流程
|
|
159
|
+
|
|
160
|
+
```typescript
|
|
161
|
+
// src/h5Adapter/hdAppAdapter.ts
|
|
162
|
+
export function hdAppAdapter() {
|
|
163
|
+
// 拦截 uni.scanCode
|
|
164
|
+
uni.scanCode = (options: UniApp.ScanCodeOptions) => {
|
|
165
|
+
// 步骤 1:参数格式转换
|
|
166
|
+
const nativeRequest = {
|
|
167
|
+
scanType: options.scanType || ['qrCode', 'barCode'],
|
|
168
|
+
hideAlbum: options.onlyFromCamera || false,
|
|
169
|
+
viewText: '扫二维码/条码',
|
|
170
|
+
language: 'zh-Hans',
|
|
171
|
+
failedMsg: '未识别到二维码,请重试',
|
|
172
|
+
screenType: 'full',
|
|
173
|
+
timeoutInterval: '10',
|
|
174
|
+
timeoutText: '未识别到二维码?'
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 步骤 2:调用 JSBridge
|
|
178
|
+
JsBridgeHandlers.handleScan(nativeRequest).then((ret) => {
|
|
179
|
+
// 步骤 3:回调格式转换
|
|
180
|
+
if (ret.resp_code === 1000) {
|
|
181
|
+
options.success?.({
|
|
182
|
+
result: ret.resp_result || '',
|
|
183
|
+
scanType: options.scanType?.[0] || 'qrCode',
|
|
184
|
+
charSet: 'utf-8',
|
|
185
|
+
path: ''
|
|
186
|
+
})
|
|
187
|
+
} else if (ret.resp_code === 10) {
|
|
188
|
+
options.fail?.({ errMsg: '用户取消扫码' })
|
|
189
|
+
} else {
|
|
190
|
+
options.fail?.({ errMsg: ret.resp_message || '扫码失败' })
|
|
191
|
+
}
|
|
192
|
+
options.complete?.(ret)
|
|
193
|
+
})
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### uni-app-api.json 的作用
|
|
199
|
+
|
|
200
|
+
这个文件标记了哪些 uni API 需要被 JSBridge 拦截替换:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
[
|
|
204
|
+
"uni.scanCode", // 需要替换
|
|
205
|
+
"uni.chooseImage", // 需要替换
|
|
206
|
+
"uni.uploadFile", // 需要替换
|
|
207
|
+
"uni.showToast", // 不需要替换(用 uni-app 的)
|
|
208
|
+
"uni.setStorage" // 不需要替换(用 uni-app 的)
|
|
209
|
+
]
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**作用**:
|
|
213
|
+
1. 文档说明:明确哪些 API 被替换了
|
|
214
|
+
2. 编译优化:某些构建工具可能会根据这个配置优化打包
|
|
215
|
+
3. 开发指南:告诉开发者哪些功能依赖原生
|
|
216
|
+
|
|
217
|
+
### 完整的架构层次
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
┌──────────────────────────────────────┐
|
|
221
|
+
│ 业务代码层 │
|
|
222
|
+
│ Pages/Components │
|
|
223
|
+
│ 调用 uni.scanCode() │
|
|
224
|
+
│ 调用 uni.chooseImage() │
|
|
225
|
+
└──────────────────────────────────────┘
|
|
226
|
+
↓ 标准 uni API 调用
|
|
227
|
+
┌──────────────────────────────────────┐
|
|
228
|
+
│ uni API 拦截适配层 │ ← 问题 2 的答案!
|
|
229
|
+
│ (hdAppAdapter.ts) │
|
|
230
|
+
│ │
|
|
231
|
+
│ 功能: │
|
|
232
|
+
│ 1. 拦截 uni API 调用 │
|
|
233
|
+
│ 2. 参数格式转换(uni → 原生) │
|
|
234
|
+
│ 3. 调用 JSBridge Handlers │
|
|
235
|
+
│ 4. 回调格式转换(原生 → uni) │
|
|
236
|
+
│ 5. 处理只读属性(UniProxy) │
|
|
237
|
+
│ │
|
|
238
|
+
│ 配置: │
|
|
239
|
+
│ - uni-app-api.json(API 清单) │
|
|
240
|
+
│ - UniProxy(处理只读属性) │
|
|
241
|
+
└──────────────────────────────────────┘
|
|
242
|
+
↓ 调用 JSBridge
|
|
243
|
+
┌──────────────────────────────────────┐
|
|
244
|
+
│ JSBridge 封装层 │
|
|
245
|
+
│ (JsBridgeHandlers.ts) │
|
|
246
|
+
│ │
|
|
247
|
+
│ 功能: │
|
|
248
|
+
│ - 业务逻辑封装 │
|
|
249
|
+
│ - 错误处理 │
|
|
250
|
+
│ - 参数校验 │
|
|
251
|
+
└──────────────────────────────────────┘
|
|
252
|
+
↓ 调用核心通信
|
|
253
|
+
┌──────────────────────────────────────┐
|
|
254
|
+
│ 核心通信层 │
|
|
255
|
+
│ (JsBridge.ts) │
|
|
256
|
+
│ │
|
|
257
|
+
│ 功能: │
|
|
258
|
+
│ - WKWebViewJavascriptBridge │
|
|
259
|
+
│ - InjectJavascript │
|
|
260
|
+
│ - 环境检测 │
|
|
261
|
+
│ - 消息收发 │
|
|
262
|
+
└──────────────────────────────────────┘
|
|
263
|
+
↓
|
|
264
|
+
Android WebView
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## 🔍 深入分析
|
|
268
|
+
|
|
269
|
+
### 为什么原设计遗漏了适配层?
|
|
270
|
+
|
|
271
|
+
**原因**:过度关注框架适配(Vue2/Vue3/React),忽略了实际项目的集成方式。
|
|
272
|
+
|
|
273
|
+
#### 原设计的想法
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
// 让业务代码这样用:
|
|
277
|
+
import { JSBridge } from '@hd-front-end/jsbridge-sdk'
|
|
278
|
+
|
|
279
|
+
JSBridge.scan().then(...) // ← 需要改业务代码
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### 实际项目的做法
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
// 业务代码不用改,还是用 uni API:
|
|
286
|
+
uni.scanCode({ success: ... }) // ← 业务代码不变
|
|
287
|
+
|
|
288
|
+
// 在 App.vue 启动时注入适配器:
|
|
289
|
+
hdAppAdapter() // ← 只改一次
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 适配层的价值
|
|
293
|
+
|
|
294
|
+
| 维度 | 没有适配层 | 有适配层 |
|
|
295
|
+
|------|-----------|---------|
|
|
296
|
+
| **业务代码修改** | 需要大量修改 | 完全不用改 |
|
|
297
|
+
| **API 风格** | Promise 风格 | uni-app 回调风格 |
|
|
298
|
+
| **迁移成本** | 高(每个调用都要改) | 低(只改一次) |
|
|
299
|
+
| **兼容性** | 不兼容 uni 生态 | 完全兼容 |
|
|
300
|
+
| **学习成本** | 需要学新 API | 无需学习 |
|
|
301
|
+
|
|
302
|
+
### 参数转换示例
|
|
303
|
+
|
|
304
|
+
#### uni-app 参数格式
|
|
305
|
+
|
|
306
|
+
```typescript
|
|
307
|
+
uni.scanCode({
|
|
308
|
+
scanType: ['qrCode', 'barCode'],
|
|
309
|
+
onlyFromCamera: true,
|
|
310
|
+
success: (res) => {},
|
|
311
|
+
fail: (err) => {},
|
|
312
|
+
complete: () => {}
|
|
313
|
+
})
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### 原生 JSBridge 参数格式
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
{
|
|
320
|
+
scanType: ['qrCode', 'barCode'],
|
|
321
|
+
hideAlbum: true,
|
|
322
|
+
viewText: '扫二维码/条码',
|
|
323
|
+
language: 'zh-Hans',
|
|
324
|
+
failedMsg: '未识别到二维码,请重试',
|
|
325
|
+
screenType: 'full',
|
|
326
|
+
timeoutInterval: '10',
|
|
327
|
+
timeoutText: '未识别到二维码?'
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**适配层的作用**:自动转换这些参数!
|
|
332
|
+
|
|
333
|
+
### 回调转换示例
|
|
334
|
+
|
|
335
|
+
#### 原生 JSBridge 返回格式
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
{
|
|
339
|
+
resp_code: 1000,
|
|
340
|
+
resp_result: 'scan-content',
|
|
341
|
+
resp_message: 'success'
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### uni-app 回调格式
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
{
|
|
349
|
+
result: 'scan-content',
|
|
350
|
+
scanType: 'qrCode',
|
|
351
|
+
charSet: 'utf-8',
|
|
352
|
+
path: ''
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**适配层的作用**:自动转换返回值并调用回调!
|
|
357
|
+
|
|
358
|
+
## 📊 对比总结
|
|
359
|
+
|
|
360
|
+
### 原设计 vs 正确架构
|
|
361
|
+
|
|
362
|
+
| 层级 | 原设计 | 正确架构 | 说明 |
|
|
363
|
+
|------|--------|---------|------|
|
|
364
|
+
| 业务代码 | 调用 `JSBridge.scan()` | 调用 `uni.scanCode()` | 无需修改业务代码 |
|
|
365
|
+
| **uni API 适配层** | **❌ 缺失** | **✅ 有(hdAppAdapter)** | **关键!** |
|
|
366
|
+
| JSBridge 封装 | ✅ 有 | ✅ 有 | 业务逻辑封装 |
|
|
367
|
+
| 核心通信 | ✅ 有 | ✅ 有 | 原生通信 |
|
|
368
|
+
|
|
369
|
+
### 迁移成本对比
|
|
370
|
+
|
|
371
|
+
#### 方案 1:没有适配层
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
// 需要修改的文件:约 200+ 个组件/页面
|
|
375
|
+
// 每个文件需要:
|
|
376
|
+
// 1. 添加 import { JSBridge } from '@hd-front-end/jsbridge-sdk'
|
|
377
|
+
// 2. 修改所有 uni.scanCode 为 JSBridge.scan
|
|
378
|
+
// 3. 修改参数格式
|
|
379
|
+
// 4. 修改回调风格(success/fail → Promise)
|
|
380
|
+
|
|
381
|
+
// 工作量:约 2-3 周
|
|
382
|
+
// 风险:高(容易遗漏)
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
#### 方案 2:有适配层
|
|
386
|
+
|
|
387
|
+
```typescript
|
|
388
|
+
// 需要修改的文件:1 个(App.vue)
|
|
389
|
+
// App.vue:
|
|
390
|
+
import { initJSBridge, hdAppAdapter } from '@hd-front-end/jsbridge-sdk'
|
|
391
|
+
|
|
392
|
+
onLaunch(async () => {
|
|
393
|
+
await initJSBridge()
|
|
394
|
+
hdAppAdapter() // ← 只加这一行!
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
// 工作量:约 2-3 天
|
|
398
|
+
// 风险:低(集中修改)
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## 💡 设计经验教训
|
|
402
|
+
|
|
403
|
+
### 教训 1:不要过度关注框架抽象
|
|
404
|
+
|
|
405
|
+
**问题**:原设计花大量精力做 Vue2/Vue3/React 适配器
|
|
406
|
+
|
|
407
|
+
**反思**:实际项目都是 uni-app,不需要支持 React
|
|
408
|
+
|
|
409
|
+
**正确做法**:专注于实际需求(uni-app 集成)
|
|
410
|
+
|
|
411
|
+
### 教训 2:要深入理解现有代码
|
|
412
|
+
|
|
413
|
+
**问题**:没有仔细研究 hdAppAdapter.ts 的作用
|
|
414
|
+
|
|
415
|
+
**反思**:这是最关键的架构层,竟然被忽略了
|
|
416
|
+
|
|
417
|
+
**正确做法**:先理解现有实现,再设计新方案
|
|
418
|
+
|
|
419
|
+
### 教训 3:要考虑迁移成本
|
|
420
|
+
|
|
421
|
+
**问题**:原设计需要大量修改业务代码
|
|
422
|
+
|
|
423
|
+
**反思**:迁移成本太高,团队不会接受
|
|
424
|
+
|
|
425
|
+
**正确做法**:设计时考虑向后兼容,降低迁移成本
|
|
426
|
+
|
|
427
|
+
## ✅ 修正后的方案
|
|
428
|
+
|
|
429
|
+
### 完整的 4 层架构
|
|
430
|
+
|
|
431
|
+
```
|
|
432
|
+
业务代码(uni.scanCode)
|
|
433
|
+
↓
|
|
434
|
+
uni API 拦截适配层(hdAppAdapter) ← 问题 2 的核心
|
|
435
|
+
↓
|
|
436
|
+
JSBridge 封装层(Handlers)
|
|
437
|
+
↓
|
|
438
|
+
核心通信层(Bridge) ← 问题 1 的差异处理在这里
|
|
439
|
+
↓
|
|
440
|
+
Android WebView
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### 核心组件
|
|
444
|
+
|
|
445
|
+
1. **hdAppAdapter.ts** - uni API 拦截适配器
|
|
446
|
+
- 拦截 uni API 调用
|
|
447
|
+
- 参数格式转换
|
|
448
|
+
- 回调格式转换
|
|
449
|
+
- 处理只读属性
|
|
450
|
+
|
|
451
|
+
2. **UniProxy.ts** - 解决 Vue3 只读属性问题
|
|
452
|
+
- 提供代理对象
|
|
453
|
+
- 兼容 Vue2/Vue3
|
|
454
|
+
|
|
455
|
+
3. **uni-app-api.json** - API 配置清单
|
|
456
|
+
- 标记哪些 API 被替换
|
|
457
|
+
- 文档说明
|
|
458
|
+
- 构建优化
|
|
459
|
+
|
|
460
|
+
4. **Bridge.ts** - 核心通信层
|
|
461
|
+
- WKWebViewJavascriptBridge
|
|
462
|
+
- 环境检测
|
|
463
|
+
- 消息收发
|
|
464
|
+
|
|
465
|
+
## 🎯 总结
|
|
466
|
+
|
|
467
|
+
### 问题 1 答案
|
|
468
|
+
|
|
469
|
+
**技术栈差别在哪?**
|
|
470
|
+
|
|
471
|
+
- **不在 JSBridge 通信本身**
|
|
472
|
+
- **而在 uni 对象的属性定义**
|
|
473
|
+
- Vue2:uni API 可写,可直接赋值
|
|
474
|
+
- Vue3:部分 uni API 只读,需要 UniProxy 代理
|
|
475
|
+
|
|
476
|
+
### 问题 2 答案
|
|
477
|
+
|
|
478
|
+
**hdAppAdapter 的位置?**
|
|
479
|
+
|
|
480
|
+
- **它是 uni API 拦截适配层**
|
|
481
|
+
- **位于业务代码和 JSBridge 之间**
|
|
482
|
+
- **作用是让业务代码无需修改**
|
|
483
|
+
- **是整个架构中最关键的一层**
|
|
484
|
+
|
|
485
|
+
### 核心价值
|
|
486
|
+
|
|
487
|
+
1. **业务代码零修改** - 继续使用 uni API
|
|
488
|
+
2. **迁移成本降低 90%** - 只需改 App.vue
|
|
489
|
+
3. **完全兼容 uni 生态** - 标准的参数和回调
|
|
490
|
+
4. **框架差异透明** - 自动处理 Vue2/Vue3 差异
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
494
|
+
**感谢你提出这两个关键问题!它们直接指出了原设计的核心缺陷!** 🙏
|
|
495
|
+
|