最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Javascript之JSBridge初探

 更新時間:2021年04月30日 09:54:37   作者:淺笑·  
這篇文章主要介紹了Javascript的JSBridge,對JSBridge感興趣的同學(xué),可以參考下

JSBridge 的起源

近些年,移動端普及化越來越高,開發(fā)過程中選用 Native 還是 H5 一直是熱門話題。Native 和 H5 都有著各自的優(yōu)缺點,為了滿足業(yè)務(wù)的需要,公司實際項目的開發(fā)過程中往往會融合兩者進行 Hybrid 開發(fā)。Native 和 H5 分處兩地,看起來無法聯(lián)系,那么如何才能讓雙方協(xié)同實現(xiàn)功能呢?

這時我們想到了 Codova ,Codova 提供了一組與設(shè)備相關(guān)的 API ,是早期js調(diào)用原生代碼來實現(xiàn)原生功能的常用方案。不過 JSBridge 真正在國內(nèi)廣泛應(yīng)用是由于移動互聯(lián)網(wǎng)的盛行。

JSBridge 是一種 JS 實現(xiàn)的 Bridge,連接著橋兩端的 Native 和 H5。它在 APP 內(nèi)方便地讓 Native 調(diào)用 JS,JS 調(diào)用 Native ,是雙向通信的通道。JSBridge 主要提供了 JS 調(diào)用 Native代碼的能力,實現(xiàn)原生功能如查看本地相冊、打開攝像頭、指紋支付等。

H5 與 Native 對比

name H5 Native
穩(wěn)定性 調(diào)用系統(tǒng)瀏覽器內(nèi)核,穩(wěn)定性較差 使用原生內(nèi)核,更加穩(wěn)定
靈活性 版本迭代快,上線靈活 迭代慢,需要應(yīng)用商店審核,上線速度受限制
受網(wǎng)速 影響 較大 較小
流暢度 有時加載慢,給用戶“卡頓”的感覺 加載速度快,更加流暢
用戶體驗 功能受瀏覽器限制,體驗有時較差 原生系統(tǒng) api 豐富,能實現(xiàn)的功能較多,體驗較好
可移植性 兼容跨平臺跨系統(tǒng),如 PC 與 移動端,iOS 與 Android 可移植性較低,對于 iOS 和 Android 需要維護兩套代碼

JSBridge 的雙向通信原理

JS 調(diào)用 Native

JS 調(diào)用 Native 的實現(xiàn)方式較多,主要有攔截URL Scheme、重寫 prompt 、注入 API 等方法。

攔截 URL Scheme

Android 和 iOS 都可以通過攔截 URL Scheme 并解析 Scheme 來決定是否進行對應(yīng)的 Native 代碼邏輯處理。

Android 的話,Webview提供了shouldOverrideUrlLoading方法來提供給 Native 攔截 H5 發(fā)送的URL Scheme請求。代碼如下:

public class CustomWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
      ......
      // 場景一: 攔截請求、接收 scheme
        if (url.equals("xxx")) {

            // handle
            ...
            // callback
            view.loadUrl("JavaScript:setAllContent(" + json + ");")
            return true;
        }
        return super.shouldOverrideUrlLoading(url);
     }
}

iOS 的WKWebview可以根據(jù)攔截到的URL Scheme和對應(yīng)的參數(shù)執(zhí)行相關(guān)的操作。代碼如下:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    if ([navigationAction.request.URL.absoluteString hasPrefix:@"xxx"]) {
        [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

這種方法的優(yōu)點是不存在漏洞問題、使用靈活,可以實現(xiàn) H5 和 Native 頁面的無縫切換。例如在某一頁面需要快速上線的情況下,先開發(fā)出 H5 頁面。某一鏈接填寫的是 H5 鏈接,在對應(yīng)的 Native 頁面開發(fā)完成前先跳轉(zhuǎn)至 H5 頁面,待 Native 頁面開發(fā)完后再進行攔截,跳轉(zhuǎn)至 Native 頁面,此時 H5 的鏈接無需進行修改。但是使用 iframe.src 來發(fā)送URL Scheme需要對 URL 的長度作控制,使用復(fù)雜,速度較慢。

重寫 prompt 等原生 JS 方法

Android 4.2 之前注入對象的接口是 addJavaScriptInterface ,但是由于安全原因慢慢不被使用。一般會通過修改瀏覽器的部分 Window 對象的方法來完成操作。主要是攔截 alert、confirm、prompt、console.log 四個方法,分別被Webview的 onJsAlert、onJsConfirm、onConsoleMessage、onJsPrompt 監(jiān)聽。其中 onJsPrompt 監(jiān)聽的代碼如下:

public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) {
  String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message,defaultValue);
  xxx;
  return true;
}

iOS 由于安全機制,WKWebView對 alert、confirm、prompt 等方法做了攔截,如果通過此方式進行 Native 與 JS 交互,需要實現(xiàn)WKWebView的三個WKUIDelegate代理方法。代碼示例如下:

-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

  UIAlertController *alertController = [UIAlertController                    alertControllerWithTitle:nil message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];

  [alertController addAction:([UIAlertAction actionWithTitle:@"確認" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {

      completionHandler();

  }])];

  [self presentViewController:alertController animated:YES completion:nil];

}

使用該方式時,可以與 Android 和 iOS 約定好使用傳參的格式,這樣 H5 可以無需識別客戶端,傳入不同參數(shù)直接調(diào)用 Native 即可。剩下的交給客戶端自己去攔截相同的方法,識別相同的參數(shù),進行自己的處理邏輯即可實現(xiàn)多端表現(xiàn)一致。如:

alert("確定xxx?", "取消", "確定", callback());

另外,如果能與 Native 確定好方法名、傳參等調(diào)用的協(xié)議規(guī)范,這樣其它格式的 prompt 等方法是不會被識別的,能起到隔離的作用。

##### 注入 API

基于Webview提供的能力,我們可以向 Window 上注入對象或方法。JS 通過這個對象或方法進行調(diào)用時,執(zhí)行對應(yīng)的邏輯操作,可以直接調(diào)用 Native 的方法。使用該方式時,JS 需要等到 Native 執(zhí)行完對應(yīng)的邏輯后才能進行回調(diào)里面的操作。

Android 的Webview提供了 addJavascriptInterface 方法,支持 Android 4.2 及以上系統(tǒng)。

gpcWebView.addJavascriptInterface(new JavaScriptInterface(), 'nativeApiBridge'); 
public class JavaScriptInterface {
    Context mContext;

  JavaScriptInterface(Context c) {
    mContext = c;
  }

  public void share(String webMessage){            
    // Native 邏輯
  }
}

JS 調(diào)用示例:

window.NativeApi.share(xxx);

iOS 的UIWebview提供了 JavaScriptScore 方法,支持 iOS 7.0 及以上系統(tǒng)。WKWebview提供了 window.webkit.messageHandlers 方法,支持 iOS 8.0 及以上系統(tǒng)。UIWebview在幾年前常用,目前已不常見。以下為創(chuàng)建WKWebViewConfiguration和 創(chuàng)建 WKWebView 示例:

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
WKPreferences *preferences = [WKPreferences new];
preferences.javaScriptCanOpenWindowsAutomatically = YES;
preferences.minimumFontSize = 40.0;
configuration.preferences = preferences;
    

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"share"];
      [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"pickImage"];
}
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.webView.configuration.userContentController     removeScriptMessageHandlerForName:@"share"];
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"pickImage"];
}

JS 調(diào)用示例:

window.webkit.messageHandlers.share.postMessage(xxx);

Native 調(diào)用 JS

Native 調(diào)用 JS 比較簡單,只要 H5 將 JS 方法暴露在 Window 上給 Native 調(diào)用即可。

Android 中主要有兩種方式實現(xiàn)。在 4.4 以前,通過 loadUrl 方法,執(zhí)行一段 JS 代碼來實現(xiàn)。在 4.4 以后,可以使用 evaluateJavascript 方法實現(xiàn)。loadUrl 方法使用起來方便簡潔,但是效率低無法獲得返回結(jié)果且調(diào)用的時候會刷新 WebView。evaluateJavascript 方法效率高獲取返回值方便,調(diào)用時候不刷新WebView,但是只支持 Android 4.4+。相關(guān)代碼如下:

webView.loadUrl("javascript:" + javaScriptString);
webView.evaluateJavascript(javaScriptString, new ValueCallback<String>() {
  @Override
  public void onReceiveValue(String value){
    xxx
  }
});

iOS 在WKWebview中可以通過 evaluateJavaScript:javaScriptString 來實現(xiàn),支持 iOS 8.0 及以上系統(tǒng)。

// swift
func evaluateJavaScript(_ javaScriptString: String, 
    completionHandler: ((Any?, Error?) -> Void)? = nil)
// javaScriptString 需要調(diào)用的 JS 代碼
// completionHandler 執(zhí)行后的回調(diào)
// objective-c
[jsContext evaluateJavaScript:@"ZcyJsBridge(ev, data)"]

JSBridge 的使用

如何引用

  • 由 H5 引用 在我司移動端初期版本時采用的是該方式,采用本地引入npm包的方式進行調(diào)用。這種方式可以確定 JSBridge 是存在的,可直接調(diào)用 Native 方法。但是如果后期 Bridge 的實現(xiàn)方式改變,雙方需要做更多的兼容,維護成本高
  • 由 Native 注入 這是當(dāng)前我司移動端選用的方式。在考慮到后期業(yè)務(wù)需要的情況下,進行了重新設(shè)計,選用 Native 注入的方式來引用 JSBridge。這樣有利于保持 API 與 Native 的一致性,但是缺點是在 Native 注入的方法和時機都受限,JS 調(diào)用 Native 之前需要先判斷 JSBridge 是否注入成功

使用規(guī)范

H5 調(diào)用 Native 方法的偽代碼實例,如:

params = {
  api_version: "xxx",    // API 版本
  title: "xxx",    // 標(biāo)題
  filename: "xxx",    // 文件名稱
  image: "xxx",    // 圖片鏈接
  url: "xxx",    // 網(wǎng)址鏈接
  success: function (res) {
    xxx;    // 調(diào)用成功后執(zhí)行
  },
  fail: function (err) {
    if (err.code == '-2') {
      fail && fail(err);    //    調(diào)用了當(dāng)前客戶端中不存在的 API 版本
    } else {
      const msg = err.msg;    //異常信息
      Toast.fail(msg);
    }
  }
};
window.NativeApi.share(params);

以下簡要列出通用方法的抽象,目前基本遵循以下規(guī)范進行雙端通信。

window.NativeApi.xxx({
    api_version:'',
    name: "xxx",
    path: "xxx",
    id:    "xxx",
    success: function (res) {
      console.log(res);
    },
    fail: function (err) {
      console.log(err);
    }
});

由于初期版本選擇了由 H5 本地引用 JSBridge,后期采用 Native 注入的方式?,F(xiàn)有的 H5 需要對各種情況做兼容,邏輯抽象如下:

reqNativeBridge(vm, fn) {
  if (!isApp()) {
    // 如果不在 APP 內(nèi)進行調(diào)用
    vm.$dialog.alert({
      message: "此功能需要訪問 APP 才能使用",
    });
  } else {
    if (!window.NativeApi) {
      // 針對初期版本
      vm.$dialog.alert({
        message: "請更新到最新 APP 使用該功能",
      });
    } else {
      // 此處只針對“調(diào)用了當(dāng)前客戶端中不存在的 API 版本”的報錯進行處理
      // 其余種類的錯誤信息交由具體的業(yè)務(wù)去處理
      fn && fn((err) => {
        vm.$dialog.alert({
          message: "請更新到最新 APP 使用該功能",
        });
      });
    }
  }
}

總結(jié)

上述內(nèi)容簡要介紹了 JSBridge 的部分原理,希望對從未了解過 JSBridge 的同學(xué)能有所幫助。如果需要更深入的了解 JSBridge 的原理和實現(xiàn),如 JSBridge 接口調(diào)用的封裝實現(xiàn),JS 調(diào)用 Native 時的回調(diào)的唯一性等。大家可以去查閱更多資料,參考更詳細的相關(guān)文檔或他人的整理成文的沉淀。

以上就是Javascript之JSBridge初探的詳細內(nèi)容,更多關(guān)于Javascript之JSBridge的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 小程序指紋驗證的實現(xiàn)代碼

    小程序指紋驗證的實現(xiàn)代碼

    這篇文章主要介紹了小程序指紋驗證的實現(xiàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • 利用JS實現(xiàn)窗口最大化和最小化效果

    利用JS實現(xiàn)窗口最大化和最小化效果

    在現(xiàn)代 Web 開發(fā)中,JavaScript 提供了多種方法來與瀏覽器窗口進行交互,包括最大化和最小化瀏覽器窗口,雖然瀏覽器通常會限制對窗口尺寸的直接控制,但我們依然可以實現(xiàn)一些常見的行為,本文將探討如何使用 JavaScript 實現(xiàn)窗口的最大化和最小化效果
    2024-12-12
  • 基于Bootstrap分頁的實例講解(必看篇)

    基于Bootstrap分頁的實例講解(必看篇)

    下面小編就為大家?guī)硪黄贐ootstrap分頁的實例講解(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 幾個javascript操作word的參考代碼

    幾個javascript操作word的參考代碼

    幾個javascript操作word的參考代碼,對于具體的調(diào)用代碼,大家可以參考我們的上一篇文章。
    2009-10-10
  • Firefox div高度自適應(yīng)

    Firefox div高度自適應(yīng)

    IE不管設(shè)置div的高度與否,都會根據(jù)內(nèi)容來自適應(yīng)高度。但是FIrefox就沒有這么聰明了。
    2009-04-04
  • javascript 在firebug調(diào)試時用console.log的方法

    javascript 在firebug調(diào)試時用console.log的方法

    當(dāng)你使用console.log()函數(shù)時,下面的firebug一定要打開,不然這函數(shù)在用firefox運行時無效且影響正常程序,如果用IE打開,將會出錯
    2012-05-05
  • js結(jié)合正則實現(xiàn)國內(nèi)手機號段校驗

    js結(jié)合正則實現(xiàn)國內(nèi)手機號段校驗

    這篇文章主要介紹了js結(jié)合正則實現(xiàn)國內(nèi)手機號段校驗的方法以及使用js和jQuery實現(xiàn)的簡單校驗手機號的示例,非常簡單實用,有需要的小伙伴可以參考下。
    2015-06-06
  • Bootstrap CSS組件之面包屑導(dǎo)航(breadcrumb)

    Bootstrap CSS組件之面包屑導(dǎo)航(breadcrumb)

    這篇文章主要為大家詳細介紹了Bootstrap CSS組件之面包屑導(dǎo)航(breadcrumb),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • 原生JS實現(xiàn)圖片懶加載(lazyload)實例

    原生JS實現(xiàn)圖片懶加載(lazyload)實例

    圖片懶加載也是比較常見的一種性能優(yōu)化的方法,本篇文章主要介紹了原生JS實現(xiàn)圖片懶加載(lazyload)實例,這里整理了詳細的代碼,有需要的小伙伴可以參考下
    2017-06-06
  • 微信小程序 彈窗自定義實例代碼

    微信小程序 彈窗自定義實例代碼

    這篇文章主要介紹了微信小程序 彈窗自定義實例代碼的相關(guān)資料,有時候做開發(fā)項目的時候需要根據(jù)客戶需求更改原系統(tǒng)的組件,這里就對小程序中彈窗進行更改,需要的朋友可以參考下
    2017-03-03

最新評論

宜昌市| 松滋市| 陆川县| 法库县| 焦作市| 县级市| 门源| 阿克苏市| 东乌| 顺义区| 淳安县| 正蓝旗| 清原| 湟中县| 株洲县| 永年县| 阆中市| 开封市| 哈尔滨市| 石狮市| 阿瓦提县| 隆昌县| 大余县| 彰化县| 永胜县| 开化县| 绵竹市| 曲沃县| 肇庆市| 肇源县| 城口县| 灯塔市| 桂东县| 吉木萨尔县| 海城市| 偃师市| 江川县| 长汀县| 绥江县| 灵石县| 建始县|