1. 程式人生 > >react native WebView 高度自適應 RN與網頁互動

react native WebView 高度自適應 RN與網頁互動

首先介紹幾個屬性和方法

1、source

    {uri: string, method: string, headers: object, body: string}, {html: string, baseUrl: string}, number

   在WebView中載入一段靜態html程式碼或者url(還可以附帶一些header選項)。

2、injectedJavaScript 

    設定在網頁載入之前注入的一段JS程式碼。

3、onMessage

在webview內部的網頁中呼叫window.postMessage方法時可以觸發此屬性對應的函式,從而實現網頁和RN之間的資料交換。

設定此屬性的同時會在webview中注入一個

postMessage的全域性函式並覆蓋可能已經存在的同名實現。

網頁端的window.postMessage只發送一個引數data,此引數封裝在RN端的event物件中,即event.nativeEvent.datadata只能是一個字串。

4、onLoadEnd

    載入結束時(無論成功或失敗)呼叫。 

一、高度自適應

例子:

第一種方法:

    首先要在初始化階段定義初始高度,如果webview的style屬性中沒有設定高度,內容會不顯示。

  constructor(props) {
    super(props);
    this.state = {
      WebViewHeight: 100,
    };
  }
    要顯示的html內容
        let html = `<!DOCTYPE html> <html lang="en"> 
            <head>
              <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <style>
              </style>
            </head> 
            <body>一些html標籤及內容
            <script>
            window.onload = function () {
              window.location.hash = 1;
              document.title = document.body.clientHeight;
            }
            </script></body>  </html>` 
在html的script中獲取高度,在WebView的onNavigationStateChange函式裡設定高度
        <WebView
                ref={'webview'}
                source={{ html: html }}
                style={{ height: this.state.WebViewHeight }}
                onNavigationStateChange={(title)=>{
                  this.setState({
                    WebViewHeight: parseInt(title.title) || 200
                  })
                }}
              />         

上面這種方法我在Android手機中有時獲取不到高度

第二種方法:
在url載入結束後,注入一段js程式碼,用來獲取url網頁的高度,然後通過與RN互動的方式,把獲取的高度通過window.postMessage傳回RN中,然後顯示
          <WebView
              ref={'webview'}
              style={{ height: this.state.WebViewHeight }}
              source={{ uri: 'https://mp.weixin.qq.com/s/ErAMhnlFXAxyLYOBhl4OTA' }}
              onLoadEnd={this.webViewLoaded}
              onMessage={(e) => {
                this.handleMessage(e)
              }}
              javaScriptEnabled={true}
            />
      webViewLoaded = () => {
          this.refs.webview.injectJavaScript(`
              const height = document.body.scrollHeight;
              window.postMessage(height);
          `);
        }
      handleMessage(e) {
        this.setState({
          WebViewHeight: e.nativeEvent.data
        });
      }

二、RN與網頁互動

1、網頁向RN傳送資料
首先在html的script定義一個傳送資料的方法
let html = `<!DOCTYPE html> <html lang="en"> 
            <head>
              <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <style>
                button: {
                   color: blue;
                }
              </style>
            </head> 
            <body>一些html標籤及內容<button>按鈕</button>
            <script>
                function sendData(data) {
                    if (window.originalPostMessage) {
                      window.postMessage(data);
                    } else {
                      throw Error('postMessage介面還未注入');
                    }
                  }
                document.getElementById('button').onclick = function() {
                    sendData('網頁向RN傳送資料');
                }
            </script>
            </body> 
            </html>`
<WebView
  ref={'webview'}
  source={{html: html}}
  style={{width: 300, height: 300}}
  onMessage={(e) => {
    this.handleMessage(e)
  }}
/>

在RN中也handleMessage為接收資料的方法,e.nativeEvent.data就是從網頁html中傳過來的資料

handleMessage(e) {
  console.log(e.nativeEvent.data)
}
2、RN網頁傳送資料

首先定義一個傳送資料的方法

sendMessage() {
  this.refs.webview.postMessage('RN向網頁傳送資料');
}
在html中也要有相應的接收資料的方法
window.onload = function () {
  document.addEventListener('message', function (e) {
    document.getElementById('button').textContent = e.data;
  });
}

以上