Web 层 Js 桥接方案


引言

在现代前端开发中,尤其是移动端混合开发,前端与原生应用之间的通信是一个常见需求。 为了解决这个问题,我们可以使用一个桥接类 AppBridge,它封装了调用原生方法和处理原生回调的逻辑。

为什么需要 AppBridge

在 WebView 中直接调用原生方法,如果每次都写原生平台判断和回调处理,代码会非常混乱。而 AppBridge 的出现正是为了:

  • 提供统一的调用接口
  • 自动处理回调,支持 Promise
  • 兼容 iOS 和 Android
  • 支持开发环境日志输出,方便调试

核心设计

单例模式

1
2
3
4
5
6
public static getInstance(): AppBridge {
if (!AppBridge.instance) {
AppBridge.instance = new AppBridge();
}
return AppBridge.instance;
}

使用单例模式保证全局只有一个桥接实例,避免重复注册回调函数。

核心属性

1
2
3
4
5
6
7
8
private static instance: AppBridge;
private __callbacks: {
[key: string]: {
resolve: (value: any) => void;
reject: (reason?: any) => void;
method: string;
};
} = {};
  • instance:存储单例实例
  • __callbacks:存储调用原生方法的回调函数

调用原生方法

1
callNative<P, R>(method: string, params: P): Promise<R>

调用流程:

  1. 生成唯一 callbackId

  2. 将 Promise 的 resolvereject 存入 __callbacks

  3. 构造调用数据

  4. 根据平台调用原生方法:

    • iOS 使用 window.webkit.messageHandlers.xxCallNative.postMessage
    • Android 使用 window.xxx.xxCallNative
1
2
3
4
5
6
# Android 端接收 web 端调用示例
@JavascriptInterface
fun xxCallNative(data: String){}

# Android 端调用 web 端示例
webView.evaluateJavascript("javascript:xxCallWeb('$json')", null);
  1. 非原生环境:

    • 开发环境输出日志
    • 生产环境抛出错误

初始化回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private initBridgeCallback() {
const oldCallback = window.ddCallWeb;
window.ddCallWeb = (callbackData: string) => {
const data = JSON.parse(callbackData);
if (this.log) console.info("nativeInvoke:", data);

if (isFunction(oldCallback)) oldCallback(data);

const { callbackId } = data;
const callback = this.__callbacks[callbackId];

if (callback) {
if (data.code === 0) callback.resolve(data.data);
else {
const error = new Error(data.msg) as Error & { response: unknown };
error.response = data;
callback.reject(error);
}
this.__callbacks = omit(this.__callbacks, callbackId);
} else {
this.dispatchNativeInvoke(data.method, data.params);
}
};
}

自动接收原生调用,将对应回调函数执行或者分发事件。

原生调用分发

1
2
3
4
5
6
7
8
9
10
11
private dispatchNativeInvoke = (method: string, params: any) => {
switch (method) {
case "route":
const path = params.router;
const type = params.type;
type === "push" ? router.push(path) : router.replace(path);
break;
default:
console.warn(`未处理的原生方法调用: ${method}`, params);
}
};

使用示例

1
2
3
4
5
6
7
8
9
const bridge = AppBridge.getInstance();

bridge.callNative("getUserInfo", { userId: 123 })
.then(res => console.log("用户信息:", res))
.catch(err => console.error("调用失败:", err));

emitter.on("onActivated", ({ route }) => {
console.log("页面激活:", route);
});

总结

AppBridge 提供了一个干净、统一的桥接方案,让前端调用原生方法和处理原生事件变得简单。其特点:

  • 单例模式,保证全局唯一
  • Promise 风格,链式调用和错误处理简单
  • 自动回调处理,兼容 iOS/Android
  • 可扩展性强,只需在 dispatchNativeInvoke 添加 case

Web 层 Js 桥接方案
https://blog.201912.xyz/2025/09/18/js-bridge/
作者
jin123d
发布于
2025年9月18日
许可协议