h5 logic_H5+app mixed development

app classification

app mainly refers to the third-party application program running on the mobile phone ~ mainly divided into the following three categories

  • Native App (native application): refers to a third-party application developed based on the mobile operating system
    • Download required (required for every update)
    • The ios/android operating systems are different, and the codes are incompatible (need to develop two sets of different codes) -> Slow development and high development costs
    • good user experience
  • Web App (web application): refers to the app developed using web technology
    • no download required
    • Cross-platform, a set of code can be used in multiple browsers -> fast development, low cost
    • The user experience is not very good, the display effect of different browsers may be different, and some functions cannot be realized
  • HyBird App (hybrid application)
    • Combining native applications and web applications, combining the advantages of native applications and web applications
    • The essence is to embed the webpage in the native app , and then generate a series of interactions~

H5 interacts with native

[1] Judging that the environment where the h5 page is opened is ios/android

Judge the operating environment of the current page through navigator.userAgent

[2] JS calls the method of ios/android
js calls the method of ios
  • In ios: If the method defined in ios wants to be called by the embedded h5 page

    • [1] Declare a method such as getAppInfo
    • [2] Register to listen to this method
        wkWebView.configuration.userContentController.add(self, name: getAppInfo)
      
  • in js

    The call in js uses a fixed syntaxwindow.webkit.messageHandlers.方法名.postMessage(数据)

    window.webkit.messageHandlers.getAppInfo.postMessage()
    
js calls the method of android
  • in android

    In android, a global variable JSBridge needs to be exposed, similar to Window in the browser environment

      // 获取webview的设置对象
      WebSettings webSettings = mWebView.getSettings()
      //  设置Android允许js脚本
      webSettings.setJavaScriptEnabled(true)
      // 暴露出JSBridge的对象到webView的全局环境
      mWebView.addJavascriptInterface(getJSBridge(), 'JSBridge')
    

    Through the above code, as long as the h5 page running by this webView can access this object!

    Tips: The variable name of the global environment is not fixed as JSBridge's
    mWebView.addJavascriptInterface(getJSBridge(), 'WBridge')
    The global environment variable name configured through the above code is WBridge

    If the attributes or methods that need to be accessed by the h5 page in the future can be added to the global variable.

  • in js

    The call in js is very simple. For example, the global variable exposed in android is JSBridge, and there is a getAppInfo method on the variable, which can be called by the following code

      Window.JSBridge.getAppInfo()
    
the difference

When calling the method of ios, it is asynchronous; when calling the method of android, it is synchronous!

Summary - Sample Code
function info() {
    
    
  if (navigator.userAgent.search(/(iphone|ipad|ipod)/i) >= 0) {
    
    
     return 'iOS' // 手机iOs
  } else if (navigator.userAgent.search(/android/i) >= 0) {
    
    
    return 'Android' // 手机安卓
  } else if (navigator.userAgent.search(/windows phone/i) >= 0) {
    
    
    return 'WinPhone'
  } else {
    
    
    return 'PC'
  }
}

const platform = info()
const params = {
    
    ...}
if (platform === 'iOS' && window.webkit) {
    
    
// showShareIcon 为ios抛出的方法
 window.webkit.messageHandlers.showShareIcon.postMessage(params)
} else if (platform === 'Android' && window.JSBridge) {
    
      
  // JSBridge为Android抛出的全局对象
   window.JSBridge.showShareIcon(JSON.stringify(params))
}else {
    
    
  return false
}
The client calls the js method

If the client wants to call the method in the web page, we need to expose the method first

tips: Sometimes the client cannot get the window, so it needs to be compatible~

const pluginFun = (function(){
    
    
  // 兼容全局对象
  const _global = (function () {
    
    
    return window || this
  }())
  const plugin = {
    
    
    方法1(){
    
    },
    方法2(){
    
    },
    ...
  }
  // 将和客户端约定的方法暴露给全局对象
  for (const i in plugin) {
    
    
    !('jsFunc' in _global) && (_global[i] = plugin[i])
  }
}())
Example: Callbacks for client-side interaction with the web

Demand scenario: There is a withdrawal function on the web page, the logic of this function is

  • [1] Call the Alipay payment channel on the client side to judge whether it is possible to withdraw cash, and the judgment result is returned to the web page
  • [2] After the web page obtains whether the withdrawal is possible: if the withdrawal is possible, call the withdrawal interface;

In vue, $on can be used for event monitoring . The specific method is as follows

  • [1] Call the client method -> judge whether it is possible to withdraw cash, and monitor the client to return the result
    isDrawal(){
          
          
      if(isAndroid){
          
          
        if (window.xxxJSBridge) {
          
          
          window.xxxJSBridge.isDrawal(url) // url是支付宝url
        }
      }
    }
    vm.$on('drawal', data=>{
          
          
      // 获取到客户端返回的信息data, 若是可以提现则调取提现接口,若是不可以提现则提示不可提现原因;
    })
    
  • [2] Encapsulate a method for the client to call to trigger the drawal event
    const pluginFun = (function(){
          
          
      // 兼容全局对象
      const _global = (function () {
          
          
        return window || this
      }())
      function callbackme(data){
          
          
        vm.$emit('drawal', data)
      }
      _global.drawal = callbackme
    }())
    
[3] The agreement between the two parties (schema)

When embedding a web page client-side

If we use methods such as $router.push to jump to the page, the page will be 当前opened in webView (equivalent to a browser page).

If we want to 新的webViewopen the page in , we need to use h5 and the client in advance 约定协议.

When the h5 page performs a page jump, the client intercepts and parses the url through the specified method. If it detects that it is a pre-agreed protocol, it calls the corresponding method~

Illustrate with the following example

  • The agreement between h5 and the client is bd-pst

  • If the url is web, open the specified h5 page in the app (the url parameter of the link)

  • If the url is non-web, call the specified page in the app

  • Example 1

    jumpPage(url){
          
          
      location.href = 'bd-pst://web?url='+encodeURIComponent(url) // 通过一个新的浏览器打开页面
    }
    
    jumpPage(url){
          
          
     this.$router.push(url)  // 在当前浏览器打开
    }
    

    Open the page as h5 page path as url

  • Example 2

      location.href='bd-pst://login'
    

    Open the login page in the app

  • It should be noted that if you use the new webView to open the page, the left return button in the tabBar cannot use $router.back (equivalent to a new browser page with empty history). But there is a jump record on the client side, and we can return the page through the method of the client side.

[4] Download the app on the web page

The download address is given to us by the client (android and ios download addresses are different), so it is necessary to determine the environment of the browser before downloading

if(navigator.userAgent.search(/(iphone|ipad|ipod)/i) >= 0){
    
    
  // ios
  location.href = 'xxx'
}else if(navigator.userAgent.search(/android/i) >= 0){
    
    
  // Android
   location.href='xxx.apk'
}else{
    
    
  // 跳转到应用宝下载
}
[5] Whether to open the page in full screen

It is often necessary to set the navbar in the h5 page, so when embedding the h5 page into the client, it involves a problem: Is the nabBar configured by the client or does it need to be written in the code of the h5 page?
The above page is an h5 page that needs to be embedded into the client, and there is a navBar on this page, so when does the navBar need to be added by the h5 developer with code and when does it not need it?

This involves configuration issues. At this time, it is necessary to pass parameters to the client need_full_screenwhether a full screen is required. If the value is false, the h5 page does not occupy the entire page, as shown in the following figure
insert image description here
h5 page size =整个屏幕 - 状态栏高度 - navbar高度

If it is true, it means that the page occupies the entire screen, as shown in the figure below,
insert image description here
the entire screen is the position of the h5 page, but a new problem arises at this time, that is, a padding-top needs to be set on the h5 page, and the value of padding-top is 状态栏的高度.

So how to get the height of the status bar? Naturally, it is obtained on the client side~

for example:

  • [1] Open the page through the bd protocol ---- 'bd-xxx://web?url=xxx?need_full_screen=1'
  • [2] The client intercepts and parses the url through the specified method, and finds that the url carries the parameter need_full_screen, then when the page is opened, the status bar height parameter is spliced ​​on the path, such as xxx?need_full_screen=1&height=40
  • [3] The h5 page gets the height and adds style through the url parameter

tabIt should be noted that the default value of need_full_screen is true in the client page (that is, the page does not have a navBar by default)

[6] Use the h5 page as the tab page of the client

[1] The need_full_screen of the tab page is true (see **[5] whether to open the page in full screen** for details)

[2] The web page is used as the tab page of the client, and the page will not be destroyed when the tab is switched, that is to say, the created life cycle function will not be followed when the page is opened again, resulting in the data not being refreshed (not the latest state). At this time, you can use the callback function to solve the problem

  • [1] Encapsulate a listening function for the client to call
    const vm = new Vue()
    
    function(){
          
          
      const _global = (function () {
          
          
        return  window || this
      }())
      function callback(data){
          
          
        vm.$emit('refresh', data)
      }
    }()
    
  • [2] Monitor the refresh method on the tab page that needs to be refreshed
    vm.$on('refresh', (data)=>{
          
          
      if(data === 'refresh'){
          
          
        //  重新调去接口
      }
    })
    

Guess you like

Origin blog.csdn.net/qq_43260366/article/details/130199516