Currently, APP is divided into the following technologies

  1. Webapp, cordova, Ionic, etc
  2. Hybrid, Native+ H5 mode
  3. React Native, weex direction
  4. Pure Native, there’s nothing to say about that
  5. This article only describes the implementation principle of Hybrid jsbrige, and will not touch on the design of Native webView. There are too many articles on webview, please refer to other articles

Communication principle

Pre-defined schema, such as myapp://… Sends a pseudo-connection request iframe.src through the front end

        var iframe = document.createElement('iframe')
        iframe.style.display = 'none'
        iframe.src = schema
        var body = document.body
        body.appendChild(iframe)
        setTimeout(function () {
            body.removeChild(iframe)
            iframe = null
        })
Copy the code

As you can see, when a button or action needs to communicate with a Native, create an iframe and then remove it. If you do not remove the iframe, there will be a large number of useless IFrame tags in the body. Here is a brief description of how Native intercepts this pseudo-link request. Override a method in the WebviewClient:

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if (url.startsWith(SCHEMA)) {
            ...
            return true; }}Copy the code

Parameter passing

In actual projects, parameters must be passed to Native to receive, which can be encapsulated in this way

        for (key in data) {
            if (data.hasOwnProperty(key)) {
                schema += '&' + key + data[key]
            }
        }
Copy the code

In this way, the form &key=value can be spliced. The Native terminal can write a method to obtain the values of key and value and then do corresponding processing.

Methods the callback

Sometimes after the bridge event is processed, some feedback needs to be told to the front-end, so the front-end needs to encapsulate a callbackName to the Native end

        var callbackName = ' '
        if (typeof callback === 'string') {
            callbackName = callback
        } else {
            callbackName = action + Date.now()
            console.log('callbackName: ' + callbackName)
            window[callbackName] = callback
        }
        schema += 'callback=' + callbackName
Copy the code

Special note: there is a date.now (), which is used to avoid repeated callbacks and to avoid blocking the UI from responding to repeated clicks on aN ios phone.

Native execution callback written:

    public static void call(WebView webview, String js) {
        if(webview ! = null) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                webview.evaluateJavascript(js, null);
            } else {
                webview.loadUrl("javacript:"+ js); }}}Copy the code

Usage, for example,

After jSbrige is packaged, it can be tested. Take sharing as an example:

      window.bridge.share({
        title: '... ',
        content: '... '
      }, function (result) {
        if (result.success) {
          alert('Share the success')}})Copy the code

Vue-based encapsulation

Simply load brige.js

import './bridge'
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App)
}).$mount('#app')
Copy the code

conclusion

  1. Don’t use UIWebview on ios, use WkWebview.
  2. Android should be aware of webView memory leaks.
  3. The front end controls the packaging volume, and webpack is not recommended because it generates a lot of webpack wrapping code.
  4. It is recommended to use rollup lightweight front-end engineering packaging without generating redundant JS code.
  5. Multi-page mode is recommended. The Native end uses methods such as pushWindow to transfer the jump right to the Native end.