Skip to content

Commit a666fcd

Browse files
committed
docs: 更新 taro native-apis 文章
1 parent 60a9b3f commit a666fcd

File tree

2 files changed

+128
-87
lines changed

2 files changed

+128
-87
lines changed

docs/.vuepress/sidebar/zh.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const zhSidebar = sidebar({
2222
"/taro/cli-init-2/",
2323
"/taro/cli-build/",
2424
"/taro/events/",
25+
"/taro/native-apis/",
2526
],
2627
},
2728
{

docs/taro/navite-apis/README.md

Lines changed: 127 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ theme: smartblue
2828
等等
2929
```
3030

31-
## 文档
31+
## 2. 文档
3232

3333
[Taro 文档 - API 说明](https://docs.taro.zone/docs/apis/about/desc)
3434

@@ -50,7 +50,7 @@ Taro.request(url).then(function (res) {
5050

5151
我们先来看 `tarojs/taro` 的代码。
5252

53-
## tarojs/taro
53+
## 3. tarojs/taro
5454

5555
```ts
5656
// packages/taro/index.js
@@ -65,7 +65,12 @@ module.exports = taro
6565
module.exports.default = module.exports
6666
```
6767

68-
## src/program.ts
68+
`hooks` 在上篇文章[Taro 4.0 已正式发布 - 5.高手都在用的发布订阅机制 Events 在 Taro 中是如何实现的?](https://juejin.cn/post/7403915119448915977#heading-20)讲过。
69+
简单来说就是 `tap` 是注册事件,`call` 是触发事件。其中 `mergeReconciler` 函数中注册`initNativeApi`函数。
70+
71+
这时我们需要来寻找 `initNativeApi` 函数在哪里实现的。可以在Taro源码中根据 `initNativeApi` 关键字搜索。或者之前的第三篇文章 [3. taro build](https://juejin.cn/post/7403193330271682612)。我们知道端平台插件的代码在 `@tarojs/plugin-platform-weapp` 包中,路径是 `packages/taro-platform-weapp/src/program.ts`
72+
73+
## 4. new Weapp 端平台插件
6974

7075
```ts
7176
// packages/taro-platform-weapp/src/program.ts
@@ -85,7 +90,11 @@ export default class Weapp extends TaroPlatformBase {
8590
}
8691
```
8792

88-
## src/runtime.ts
93+
`runtimePath` 路径:`@tarojs/plugin-platform-weapp/dist/runtime`
94+
95+
对应的运行时路径 `packages/taro-platform-weapp/src/runtime.ts`
96+
97+
## 5. 运行时 src/runtime.ts
8998

9099
```ts
91100
// packages/taro-platform-weapp/src/runtime.ts
@@ -97,7 +106,12 @@ mergeReconciler(hostConfig)
97106
mergeInternalComponents(components)
98107
```
99108

100-
## mergeReconciler
109+
- 使用 mergeReconciler 函数把自定义的 hostConfig 合并到全局 [Reconciler](https://docs.taro.zone/docs/platform-plugin/reconciler) 中。
110+
- 使用 mergeInternalComponents 函数把自定义组件信息 [components.ts](https://docs.taro.zone/docs/platform-plugin/platform-mini#31-%E7%BC%96%E5%86%99-componentsts) 合并到全局 internalComponents 组件信息对象中。
111+
112+
我们来看下 `mergeReconciler` 函数的实现。
113+
114+
## 6. mergeReconciler 函数
101115

102116
```ts
103117
// packages/shared/src/utils.ts
@@ -109,14 +123,11 @@ export function mergeReconciler (hostConfig, hooksForTest?) {
109123
obj.tap(key, hostConfig[key])
110124
})
111125
}
112-
113126
```
114127

115-
```ts
116-
// packages/shared/src/utils.ts
117-
```
128+
`obj.tap(key, hostConfig[key])` 是注册事件,在 `call` 调用。
118129

119-
## hostConfig
130+
## 7. hostConfig
120131

121132
```ts
122133
// packages/taro-platform-weapp/src/runtime-utils.ts
@@ -139,25 +150,19 @@ export const hostConfig = {
139150
return config
140151
},
141152
transferHydrateData (data, element, componentsAlias) {
142-
if (element.isTransferElement) {
143-
const pages = getCurrentPages()
144-
const page = pages[pages.length - 1]
145-
data[Shortcuts.NodeName] = element.dataName
146-
page.setData({
147-
[toCamelCase(data.nn)]: data
148-
})
149-
return {
150-
sid: element.sid,
151-
[Shortcuts.Text]: '',
152-
[Shortcuts.NodeName]: componentsAlias['#text']?._num || '8'
153-
}
154-
}
153+
// 省略若干代码
155154
},
156155
}
157156

158157
```
159158

160-
## initNativeApi 初始化原始 api
159+
我们接着来看 `initNativeApi` 函数。
160+
161+
## 8. initNativeApi 初始化原始 api
162+
163+
```ts
164+
// packages/taro-platform-weapp/src/apis.ts
165+
```
161166

162167
```ts
163168
// packages/taro-platform-weapp/src/apis.ts
@@ -198,7 +203,9 @@ export function initNativeApi (taro) {
198203

199204
```
200205

201-
## processApis 处理 apis
206+
`initNativeApi` 函数中调用了 `processApis` 函数,把 `wx` 的 api 转换成 `taro` 的 api。我们接着来看 `processApis` 函数的具体实现。
207+
208+
## 9. processApis 处理 apis
202209

203210
```ts
204211
// packages/shared/src/native-apis.ts
@@ -209,15 +216,21 @@ const needPromiseApis = new Set<string>([
209216
'chooseAddress', 'chooseImage', 'chooseLocation', 'downloadFile','getLocation', 'navigateBack', 'navigateTo', 'openDocument', 'openLocation', 'reLaunch', 'redirectTo', 'scanCode', 'showModal', 'showToast', 'switchTab', 'uploadFile',
210217
])
211218

219+
// processApis 参数对象
212220
interface IProcessApisIOptions {
213221
// 不需要 promisify 的 api
214222
noPromiseApis?: Set<string>
215-
// 希望 promisify 的 api
223+
// 需要 promisify 的 api
216224
needPromiseApis?: Set<string>
225+
// handleSyncApis 磨平差异
217226
handleSyncApis?: (key: string, global: IObject, args: any[]) => any
227+
// 改变 key 或 option 字段,如需要把支付宝标准的字段对齐微信标准的字段
218228
transformMeta?: (key: string, options: IObject) => { key: string, options: IObject }
229+
// 修改 apis
219230
modifyApis?: (apis: Set<string>) => void
231+
// 修改返回结果
220232
modifyAsyncResult?: (key: string, res) => void
233+
// 是否只 promisify,只在 plugin-inject 端使用
221234
isOnlyPromisify?: boolean
222235
[propName: string]: any
223236
}
@@ -227,6 +240,9 @@ function processApis (taro, global, config: IProcessApisIOptions = {}) {
227240
}
228241
```
229242

243+
是否只 `promisify`,只在 `@tarojs/plugin-inject` 插件使用
244+
> 可以为小程序平台注入公共的组件、API 等逻辑
245+
230246
```ts
231247
// packages/shared/src/native-apis.ts
232248
function processApis (taro, global, config: IProcessApisIOptions = {}) {
@@ -266,7 +282,18 @@ function processApis (taro, global, config: IProcessApisIOptions = {}) {
266282

267283
```
268284

269-
### apis.forEach 需要 promisify 的 api 逻辑
285+
### 9.1 apis.forEach 需要 promisify 的 api 逻辑
286+
287+
`nonsupport` 函数
288+
289+
```ts
290+
// packages/shared/src/utils.ts
291+
export function nonsupport (api) {
292+
return function () {
293+
console.warn(`小程序暂不支持 ${api}`)
294+
}
295+
}
296+
```
270297

271298
```js
272299
// packages/shared/src/native-apis.ts
@@ -303,43 +330,12 @@ apis.forEach(key => {
303330

304331
// Promise 化
305332
const p: any = new Promise((resolve, reject) => {
306-
obj.success = res => {
307-
config.modifyAsyncResult?.(key, res)
308-
options.success?.(res)
309-
if (key === 'connectSocket') {
310-
resolve(
311-
Promise.resolve().then(() => task ? Object.assign(task, res) : res)
312-
)
313-
} else {
314-
resolve(res)
315-
}
316-
}
317-
obj.fail = res => {
318-
options.fail?.(res)
319-
reject(res)
320-
}
321-
obj.complete = res => {
322-
options.complete?.(res)
323-
}
324-
if (args.length) {
325-
task = global[key](obj, ...args)
326-
} else {
327-
task = global[key](obj)
328-
}
333+
// 省略...,拆开在下方
329334
})
330335

331336
// 给 promise 对象挂载属性
332337
if (['uploadFile', 'downloadFile'].includes(key)) {
333-
equipTaskMethodsIntoPromise(task, p)
334-
p.progress = cb => {
335-
task?.onProgressUpdate(cb)
336-
return p
337-
}
338-
p.abort = cb => {
339-
cb?.()
340-
task?.abort()
341-
return p
342-
}
338+
// 省略实现...
343339
}
344340
return p
345341
}
@@ -349,46 +345,90 @@ apis.forEach(key => {
349345
})
350346
```
351347

348+
`promisify` 具体实现
349+
352350
```ts
353-
// packages/shared/src/utils.ts
354-
export function nonsupport (api) {
355-
return function () {
356-
console.warn(`小程序暂不支持 ${api}`)
357-
}
351+
// Promise 化
352+
const p: any = new Promise((resolve, reject) => {
353+
obj.success = res => {
354+
config.modifyAsyncResult?.(key, res)
355+
options.success?.(res)
356+
if (key === 'connectSocket') {
357+
resolve(
358+
Promise.resolve().then(() => task ? Object.assign(task, res) : res)
359+
)
360+
} else {
361+
resolve(res)
362+
}
363+
}
364+
obj.fail = res => {
365+
options.fail?.(res)
366+
reject(res)
367+
}
368+
obj.complete = res => {
369+
options.complete?.(res)
370+
}
371+
if (args.length) {
372+
task = global[key](obj, ...args)
373+
} else {
374+
task = global[key](obj)
375+
}
376+
})
377+
```
378+
379+
```ts
380+
// 给 promise 对象挂载属性
381+
if (['uploadFile', 'downloadFile'].includes(key)) {
382+
// 省略实现...
383+
equipTaskMethodsIntoPromise(task, p)
384+
p.progress = cb => {
385+
task?.onProgressUpdate(cb)
386+
return p
387+
}
388+
p.abort = cb => {
389+
cb?.()
390+
task?.abort()
391+
return p
392+
}
358393
}
394+
359395
```
360396

361-
### apis.forEach 不需要 promisify 的 api 逻辑
397+
### 9.2 apis.forEach 不需要 promisify 的 api 逻辑
362398

363399
```ts
364400
// packages/shared/src/native-apis.ts
365-
let platformKey = key
366-
367-
// 改变 key 或 option 字段,如需要把支付宝标准的字段对齐微信标准的字段
368-
if (config.transformMeta) {
369-
platformKey = config.transformMeta(key, {}).key
370-
}
401+
if (_needPromiseApis.has(key)) {
402+
// 省略,上方
403+
} else {
404+
let platformKey = key
405+
// 改变 key 或 option 字段,如需要把支付宝标准的字段对齐微信标准的字段
406+
if (config.transformMeta) {
407+
platformKey = config.transformMeta(key, {}).key
408+
}
371409

372-
// API 不存在
373-
if (!global.hasOwnProperty(platformKey)) {
374-
taro[key] = nonsupport(key)
375-
return
376-
}
377-
if (isFunction(global[key])) {
378-
taro[key] = (...args) => {
379-
if (config.handleSyncApis) {
380-
return config.handleSyncApis(key, global, args)
381-
} else {
382-
return global[platformKey].apply(global, args)
410+
// API 不存在
411+
if (!global.hasOwnProperty(platformKey)) {
412+
taro[key] = nonsupport(key)
413+
return
414+
}
415+
if (isFunction(global[key])) {
416+
taro[key] = (...args) => {
417+
if (config.handleSyncApis) {
418+
return config.handleSyncApis(key, global, args)
419+
} else {
420+
return global[platformKey].apply(global, args)
421+
}
383422
}
423+
} else {
424+
// 属性类型
425+
taro[key] = global[platformKey]
384426
}
385-
} else {
386-
// 属性类型
387-
taro[key] = global[platformKey]
388427
}
428+
389429
```
390430

391-
## 总结
431+
## 10. 总结
392432

393433
## links
394434

0 commit comments

Comments
 (0)