JSBridge 原理
理解 JSBridge 的命名由来和实现方式
问题
为什么叫 “JS” Bridge?JSBridge 是如何实现 Web 与 Native 通信的?
解答
为什么是 “JS” Bridge
因为在 Hybrid App 中,JavaScript 是唯一能在 WebView 中运行并与 Native 交互的语言。
- WebView 本质是一个浏览器内核,只能执行 JS
- Native(iOS/Android)无法直接操作网页 DOM
- 所以必须通过 JS 作为”桥梁”来传递消息
简单说:JS 是 Web 端唯一的出口,所有通信都要经过它。
通信原理
JSBridge 的通信是双向的:
┌─────────────┐ ┌─────────────┐
│ WebView │ ←── JSBridge ──→ │ Native │
│ (JS) │ │ (iOS/Android)│
└─────────────┘ └─────────────┘
JS 调用 Native
方式一:注入 API(推荐)
Native 向 WebView 的 window 对象注入方法:
// Native 注入后,JS 可以直接调用
window.NativeBridge.showToast('Hello')
window.NativeBridge.getLocation((data) => {
console.log(data.lat, data.lng)
})
方式二:URL Scheme 拦截
JS 通过修改 URL,Native 拦截并解析:
// JS 端发起调用
function callNative(method, params, callback) {
const callbackId = `cb_${Date.now()}`
// 存储回调函数
window[callbackId] = callback
// 构造 scheme URL
const url = `myapp://${method}?params=${encodeURIComponent(JSON.stringify(params))}&callback=${callbackId}`
// 通过 iframe 发起请求(不会引起页面跳转)
const iframe = document.createElement('iframe')
iframe.style.display = 'none'
iframe.src = url
document.body.appendChild(iframe)
setTimeout(() => iframe.remove(), 100)
}
// 使用
callNative('share', { title: '分享标题' }, (result) => {
console.log('分享结果:', result)
})
Native 调用 JS
Native 直接执行 WebView 中的 JS 代码:
// JS 端:暴露全局方法供 Native 调用
window.onNativeEvent = function(eventName, data) {
console.log('收到 Native 事件:', eventName, data)
// 处理事件...
}
// Native 端(伪代码):
// iOS: webView.evaluateJavaScript("onNativeEvent('login', {userId: 123})")
// Android: webView.evaluateJavascript("onNativeEvent('login', {userId: 123})", null)
完整的 JSBridge 封装
const JSBridge = {
callbacks: {},
callbackId: 0,
// JS 调用 Native
call(method, params = {}) {
return new Promise((resolve) => {
const id = ++this.callbackId
this.callbacks[id] = resolve
// 如果 Native 注入了方法,直接调用
if (window.NativeBridge && window.NativeBridge[method]) {
window.NativeBridge[method](JSON.stringify({ ...params, callbackId: id }))
} else {
// 降级使用 URL Scheme
const iframe = document.createElement('iframe')
iframe.src = `myapp://${method}?data=${encodeURIComponent(JSON.stringify({ ...params, callbackId: id }))}`
iframe.style.display = 'none'
document.body.appendChild(iframe)
setTimeout(() => iframe.remove(), 100)
}
})
},
// 供 Native 回调
onCallback(id, result) {
const callback = this.callbacks[id]
if (callback) {
callback(result)
delete this.callbacks[id]
}
},
// 供 Native 主动调用
onEvent(eventName, data) {
const event = new CustomEvent(`native:${eventName}`, { detail: data })
window.dispatchEvent(event)
}
}
// 暴露给 Native
window._jsBridge = JSBridge
// 使用示例
async function share() {
const result = await JSBridge.call('share', { title: '标题', url: location.href })
console.log('分享结果:', result)
}
// 监听 Native 事件
window.addEventListener('native:login', (e) => {
console.log('用户登录:', e.detail)
})
关键点
- JS 是桥梁:WebView 只能运行 JS,所以 Web 与 Native 的通信必须经过 JS
- JS → Native:注入 API(直接调用)或 URL Scheme 拦截(iframe/location)
- Native → JS:通过
evaluateJavaScript执行 JS 代码 - 回调机制:通过 callbackId 匹配请求和响应,实现异步回调
- 双向通信:JSBridge 本质是一套约定好的消息传递协议
目录