原理
支付宝小程序webview可以通过postMessage向小程序发送消息,参考webview
小程序也可以通过webViewContext.postMessage向h5发送消息,参考webViewContext
基于以上两点,我们可以实现类似于rpc的jsbridge
依赖包实现思路
h5端依赖包需要实现以下两个功能:
- 直接调用jsbridge方法,执行小程序代码(发送消息)
- 通过promisify接收返回值(接收消息)
代码实现
假如我们现在要实现一个调用小程序获取用户信息的方法
- 定义方法名
首先我们定义一个方法叫getUserInfo
- 发送消息
因为我们可能还要传参数,通过以下方法调用
my.postMessage({
method: 'getUserInfo',
params: {
name: true,
age: false
}
})
- 接收消息以及返回消息
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" />
- h5接收消息
my.onMessage = function(e) {
console.log(e); // {status: 200, message: '请求成功'}
}
- 接下来就是将h5端promisify化,需要考虑以下几个因素
-
- 回调函数名称需要window唯一
- 根据接口规则,成功进入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})
}
- 最后h5就可以愉快调用了
getUserInfo().then(res => {
console.log('成功拿到数据', res)
}).catch(console.error)