支付宝小程序之jsbridge插件开发

478 阅读1分钟

原理

支付宝小程序webview可以通过postMessage向小程序发送消息,参考webview

小程序也可以通过webViewContext.postMessage向h5发送消息,参考webViewContext

基于以上两点,我们可以实现类似于rpc的jsbridge

依赖包实现思路

h5端依赖包需要实现以下两个功能:

  • 直接调用jsbridge方法,执行小程序代码(发送消息)
  • 通过promisify接收返回值(接收消息)

代码实现

假如我们现在要实现一个调用小程序获取用户信息的方法

  1. 定义方法名

首先我们定义一个方法叫getUserInfo

  1. 发送消息

因为我们可能还要传参数,通过以下方法调用

my.postMessage({
  method: 'getUserInfo',
  params: {
    name: true,
    age: false
  }
})
  1. 接收消息以及返回消息
const webViewContext = useRef(null)
useEffect(() => {
  webViewContext.current = my.createWebViewContext('web-view-1')
}, [])

function onMessage(e) {
  webViewContext.current.postMessage({
    method: e.detail.callback, // 回调需要执行的方法名
    data: {
      name: '观观',
      age: 18
    },
    status: 200,
    message: '请求成功'
  })
}

<WebView id="web-view-1" src="..." onMessage="onMessage" />
  1. h5接收消息
my.onMessage = function(e) {
  console.log(e); // {status: 200, message: '请求成功'}
}
  1. 接下来就是将h5端promisify化,需要考虑以下几个因素
    1. 回调函数名称需要window唯一
    2. 根据接口规则,成功进入then,返回data,失败报错返回res
window.callbackList = {}

function getRandomCallbackId(name) {
  return `${"wywk"}_${Date.now()}_${name}`;
}

function invoke(methodName) {
  return new Promise((resolve, reject) => {
    try {
      const callbackId = getRandomCallbackId(methodName)
    
      // 定义回调方法
      callbackList[callbackId] = (res) => {
        const { status } = res
        if (status === 200) {
          resolve(data)
        } else {
          reject(res)
        }
      }
  
      my.postMessage({
        callback: callbackId,
        method: methodName,
        params: {
          name: true,
          age: false
        }
      })
    } catch (e) {
      reject({
        data: e,
        message: '执行异常'
      })
    }
  })
}

function getUserInfo() {
  return invoke('getUserInfo')
}

my.onMessage = function(e) {
  const { methodName, ...other } = e
  window[methodName]({...other})
}
  1. 最后h5就可以愉快调用了
getUserInfo().then(res => {
  console.log('成功拿到数据', res)
}).catch(console.error)