Taro 3.1.0 源码分析


@tarojs/taro

import Taro, { useDidShow } from '@tarojs/taro'

我们用的最频繁的包就是 @tarojs/taro

// taro/index.js
const { CurrentReconciler } = require('@tarojs/runtime')
const taro = require('@tarojs/api').default

if (typeof CurrentReconciler.initNativeApi === 'function') {
  CurrentReconciler.initNativeApi(taro)
}

module.exports = taro
module.exports.default = module.exports

// taro-runtime/reconciler.ts
export const CurrentReconciler: Reconciler = Object.assign({
  getLifecyle (instance, lifecyle) {
    return instance[lifecyle]
  },
  getPathIndex (indexOfNode) {
    return `[${indexOfNode}]`
  },
  getEventCenter (Events) {
    return new Events()
  }
}, defaultReconciler)

// shared/utils.ts
export const defaultReconciler = {}

export function mergeReconciler (hostConfig) {
  Object.assign(defaultReconciler, hostConfig)
}

// taro-weapp/src/runtime/ts
import { mergeReconciler, mergeInternalComponents } from '@tarojs/shared'
import { hostConfig, components } from './runtime-utils'

mergeReconciler(hostConfig)
mergeInternalComponents(components)

Taro 根据不同的编译环境变量,引入了对应的编译包。
编译包引入的是一个 initNativeAPI 初始化函数,用于初始化对应平台的原生 API。

@tarojs/taro-weapp

微信小程序平台initNativeApi所做的事情就是将微信的 API 进行一些二次封装,然后转成挂载在 Taro 对象下,开发者调用 Taro 的 API 即可调用到微信官方 API。

export function initNativeApi (taro) {
  processApis(taro, wx, {
    noPromiseApis,
    needPromiseApis
  })
  taro.cloud = wx.cloud
}

processApis 收集了当前运行平台的 _noPromiseApis_needPromiseApis,将_needPromiseApis的api Promise 化,都绑定到Taro对象上。

request

processApis也做了Taro.request 请求改造,将Taro.request 绑定 new taro.Link

/**
 * 挂载常用 API
 * @param taro Taro 对象
 * @param global 小程序全局对象,如微信的 wx,支付宝的 my
 */
function equipCommonApis (taro, global, apis: Record = {}) {
  ...
  // request & interceptors
  const request = apis.request ? apis.request : getNormalRequest(global)
  function taroInterceptor (chain) {
    return request(chain.requestParams)
  }
  const link = new taro.Link(taroInterceptor)
  taro.request = link.request.bind(link)
  taro.addInterceptor = link.addInterceptor.bind(link)
  taro.cleanInterceptors = link.cleanInterceptors.bind(link)
  taro.miniGlobal = global
}

// taro-api/interceptor/index.js
export default class Link {
  constructor (interceptor) {
    this.taroInterceptor = interceptor
    this.chain = new Chain()
  }

  request (requestParams) {
    this.chain.interceptors = this.chain.interceptors.filter(interceptor => interceptor !== this.taroInterceptor)
    this.chain.interceptors.push(this.taroInterceptor)
    return this.chain.proceed({ ...requestParams })
  }

  addInterceptor (interceptor) {
    this.chain.interceptors.push(interceptor)
  }

  cleanInterceptors () {
    this.chain = new Chain()
  }
}

到这里,@tarojs/taro 就已经解析完成了


待续