1.0.0 • Published 7 months ago

@docoi/jsbridge-sdk v1.0.0

Weekly downloads
-
License
MIT
Repository
-
Last release
7 months ago

JSBridge SDK

轻量级、高性能的 JSBridge SDK,用于 Web 与原生 App 之间的通信。

特性

  • 🚀 高性能:轻量级设计,无外部依赖,体积小巧
  • 🔄 双向通信:支持 H5 调用原生方法,也支持原生调用 H5 方法
  • 📱 多平台支持:同时支持 iOS (WKWebView) 和 Android (JavaScriptInterface)
  • 🔄 队列管理:内置队列机制,确保顺序调用,避免并发问题
  • 💾 缓存支持:可配置接口缓存,提高频繁调用的性能
  • 📊 调试友好:内置日志系统,支持不同级别的调试输出
  • 🔌 事件系统:提供订阅/发布模式的事件系统,方便原生向 H5 推送消息
  • 🔄 Promise 支持:支持 Promise 方式调用,代码更简洁
  • 🧩 TypeScript:使用 TypeScript 编写,提供完整类型定义
  • 🛡️ 框架兼容:适用于各种前端框架 (Vue, React, Angular 等)

安装

npm install jsbridge-sdk --save

或者使用 CDN 直接引入:

<script src="https://unpkg.com/jsbridge-sdk/dist/jsbridge.min.js"></script>

基本用法

初始化

import JSBridge from 'jsbridge-sdk';

// 初始化 JSBridge
JSBridge.init({
  debug: true,             // 是否开启调试模式
  timeout: 15000,          // 请求超时时间(毫秒)
  enableCache: true        // 是否启用缓存
});

调用原生方法

// 方式 1:回调方式
JSBridge.call('getDeviceInfo', function(result) {
  console.log('设备信息:', result);
});

// 方式 2:带参数
JSBridge.call('getLocation', { type: 'gcj02' }, function(result) {
  console.log('位置信息:', result);
});

// 方式 3:Promise 方式
JSBridge.callAsync('getNetworkStatus')
  .then(result => {
    console.log('网络状态:', result);
  })
  .catch(error => {
    console.error('获取网络状态失败:', error);
  });

注册 H5 方法供原生调用

// 注册方法
JSBridge.register('updateUI', function(data) {
  console.log('收到原生传来的数据:', data);
  // 更新界面逻辑
  return {
    success: true,
    message: '界面已更新'
  };
});

// 注销方法
JSBridge.unregister('updateUI');

事件监听

// 监听事件
function networkChangeHandler(data) {
  console.log('网络状态变化:', data);
}
JSBridge.on('networkChange', networkChangeHandler);

// 取消监听
JSBridge.off('networkChange', networkChangeHandler);

在 Vue 中使用

创建插件

// src/plugins/jsbridge.js
import JSBridge from 'jsbridge-sdk';

export default {
  install(app, options = {}) {
    // 初始化 JSBridge
    JSBridge.init({
      debug: options.debug || false,
      enableCache: options.enableCache !== false,
      timeout: options.timeout || 15000
    });

    // 添加全局属性 $jsbridge
    app.config.globalProperties.$jsbridge = JSBridge;

    // 提供 JSBridge
    app.provide('jsbridge', JSBridge);
  }
};

// 导出 JSBridge 单例,方便直接使用
export { JSBridge };

在 main.js 中注册插件

import { createApp } from 'vue';
import App from './App.vue';
import JSBridgePlugin from './plugins/jsbridge';

const app = createApp(App);
app.use(JSBridgePlugin, { debug: true });
app.mount('#app');

在组件中使用

// 选项式 API
export default {
  methods: {
    getDeviceInfo() {
      this.$jsbridge.call('getDeviceInfo', result => {
        this.deviceInfo = result;
      });
    }
  }
};

// 组合式 API
import { inject } from 'vue';

export default {
  setup() {
    const jsbridge = inject('jsbridge');

    const getDeviceInfo = async () => {
      try {
        const result = await jsbridge.callAsync('getDeviceInfo');
        // 处理结果
      } catch (err) {
        // 处理错误
      }
    };

    return { getDeviceInfo };
  }
};

原生端实现

本 SDK 提供 JavaScript 端的实现,原生端需要实现相应的接口才能完成通信。

iOS 实现(WKWebView)

// 简化示例
extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard let body = message.body as? [String: Any],
              let methodName = body["method"] as? String,
              let params = body["params"] as? [String: Any],
              let callbackId = body["callbackId"] as? String else {
            return
        }

        // 处理方法调用
        handleJSBridgeCall(methodName: methodName, params: params, callbackId: callbackId)
    }

    func handleJSBridgeCall(methodName: String, params: [String: Any], callbackId: String) {
        // 根据方法名执行相应的原生操作
        var result: [String: Any] = [:]

        switch methodName {
        case "getDeviceInfo":
            // 获取设备信息
            result = ["platform": "iOS", "version": UIDevice.current.systemVersion]
        // 其他方法...
        default:
            result = ["error": "方法不存在"]
        }

        // 返回结果给 JS
        let script = "window.JSBridgeCallback('\(callbackId)', \(toJSONString(result)))"
        webView.evaluateJavaScript(script, completionHandler: nil)
    }

    // 调用 JS 方法
    func callJSMethod(name: String, data: [String: Any], completion: ((Any?) -> Void)? = nil) {
        let script = "window.JSBridgeInvoke('\(name)', \(toJSONString(data)))"
        webView.evaluateJavaScript(script) { (result, error) in
            completion?(result)
        }
    }

    // 触发事件
    func triggerJSEvent(eventName: String, data: [String: Any]) {
        let script = "window.JSBridgeEvent('\(eventName)', \(toJSONString(data)))"
        webView.evaluateJavaScript(script, completionHandler: nil)
    }
}

Android 实现(JavaScriptInterface)

// 简化示例
public class JSBridgeInterface {
    private WebView webView;
    private Context context;

    public JSBridgeInterface(WebView webView, Context context) {
        this.webView = webView;
        this.context = context;
    }

    @JavascriptInterface
    public void call(String message) {
        try {
            JSONObject jsonObject = new JSONObject(message);
            String method = jsonObject.getString("method");
            JSONObject params = jsonObject.optJSONObject("params");
            String callbackId = jsonObject.getString("callbackId");

            // 根据方法名执行相应操作
            JSONObject result = handleMethod(method, params);

            // 返回结果给 JS
            callJSCallback(callbackId, result);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private JSONObject handleMethod(String method, JSONObject params) throws JSONException {
        JSONObject result = new JSONObject();

        switch (method) {
            case "getDeviceInfo":
                // 获取设备信息
                result.put("platform", "Android");
                result.put("version", Build.VERSION.RELEASE);
                break;
            // 其他方法...
            default:
                result.put("error", "方法不存在");
        }

        return result;
    }

    // 在主线程中调用 JS 回调
    private void callJSCallback(final String callbackId, final JSONObject result) {
        webView.post(() -> {
            webView.evaluateJavascript(
                "window.JSBridgeCallback('" + callbackId + "', " + result.toString() + ")",
                null
            );
        });
    }

    // 在主线程中调用 JS 方法
    public void callJSMethod(String name, JSONObject data, ValueCallback<String> callback) {
        webView.post(() -> {
            webView.evaluateJavascript(
                "window.JSBridgeInvoke('" + name + "', " + data.toString() + ")",
                callback
            );
        });
    }

    // 在主线程中触发 JS 事件
    public void triggerJSEvent(String eventName, JSONObject data) {
        webView.post(() -> {
            webView.evaluateJavascript(
                "window.JSBridgeEvent('" + eventName + "', " + data.toString() + ")",
                null
            );
        });
    }

    @JavascriptInterface
    public void onJSBridgeReady() {
        // Bridge 已就绪
        Log.d("JSBridge", "Bridge is ready");
    }
}

示例

查看 examples 目录中的完整示例:

  • examples/basic.html - 基本用法示例
  • examples/vue-demo/ - Vue 集成示例

API 文档

JSBridge

方法

  • init(options?: JSBridgeOptions): JSBridgeInterface - 初始化 JSBridge
  • call(method: string, params?: any, callback?: CallbackFunction): JSBridgeInterface - 调用原生方法
  • callAsync(method: string, params?: any): Promise<any> - Promise 风格的原生方法调用
  • register(name: string, handler: MethodHandler): JSBridgeInterface - 注册 H5 方法供原生调用
  • unregister(name: string): JSBridgeInterface - 注销 H5 方法
  • on(eventName: string, handler: EventHandler): JSBridgeInterface - 监听原生事件
  • off(eventName: string, handler?: EventHandler): JSBridgeInterface - 取消监听原生事件
  • setDebug(enabled: boolean, options?: Partial<DebugOptions>): JSBridgeInterface - 设置调试模式
  • clearCache(): JSBridgeInterface - 清除所有缓存

类型定义

interface JSBridgeOptions {
  debug?: boolean;
  timeout?: number;
  enableCache?: boolean;
}

type CallbackFunction = (data: any) => void;
type MethodHandler = (data: any) => any | Promise<any>;
type EventHandler = (data: any) => void;

interface DebugOptions {
  enabled: boolean;
  logLevel?: string;
  useConsole?: boolean;
}

构建与开发

# 安装依赖
npm install

# 开发模式
npm run dev

# 构建
npm run build

# 运行示例
npm run example:basic
1.0.0

7 months ago