在實際開發中,我們通常會嵌入一些html頁面,官方為我們提供了一個非常好用的網頁組件WebView,通過這個組件我們可以通過傳入一個url或者是傳入一段html
一. WebView的基本屬性方法介紹與使用
主要屬性介紹
- source:在 WebView 中載入一段靜態的 html 代碼或是傳入一個 url(還可以附帶一些 header 選項)
- automaticallyAdjustContentInsets:設置是否自動調整內容。格式:bool。默認值為true
- contentInset:設置內容所占的尺寸大小。格式:{top:number,left:number,bottom:number,right:number}
- injectedJavaScript(String):當網頁加載之前注入一段 js 代碼。其值是字符串形式。
- startInLoadingState:是否開啟頁面加載的狀態,其值為 true 或者 false。
- bounces(僅iOS):回彈特性。默認為 true。如果設置為 false,則內容拉到底部或者頭部都不回彈。
- scalesPageToFit(僅iOS):用於設置網頁是否縮放自適應到整個屏幕視圖,以及用戶是否可以改變縮放頁面。
- scrollEnabled(僅iOS):用於設置是否開啟頁面滾動。
- domStorageEnabled(僅Android):用於控制是否開啟 DOM Storage(存儲)。
- javaScriptEnabled(僅Android):是否開啟 JavaScript,在 iOS 中的 WebView 是默認開啟的。
主要方法介紹
- onNavigationStateChange:當導航狀態發生變化的時候調用。
- onLoadStart:當網頁開始加載的時候調用。
- onError:當網頁加載失敗的時候調用。
- onLoad:當網頁加載結束的時候調用。
- onLoadEnd:當網頁加載結束調用,不管是成功還是失敗。
- renderLoading:WebView組件正在渲染頁面時觸發的函數,只有 startInLoadingState 為 true 時該函數才起作用。
- renderError:監聽渲染頁面出錯的函數。
- onShouldStartLoadWithRequest(僅iOS):該方法允許攔截 WebView 加載的 URL 地址,進行自定義處理。該方法通過返回 true 或者 falase 來決定是否繼續加載該攔截到請求。
- onMessage:在webView內部網頁中,調用window.postMessage可以觸發此屬性對應的函數,通過event.nativeEvent.data獲取接收到的數據,實現網頁和RN之間的數據傳遞
- injectJavaScript(function):函數接受一個字符串,該字符串將傳遞給WebView,並立即執行為JavaScript。
通過url加載一個頁面
render() {
return (
<View style={styles.container}>
<WebView
ref={webView => this.webView = webView}
startInLoadingState={true}
onNavigationStateChange={e => this.onNavigationStateChange(e)}
source={{ uri: 'https://github.com/xxxxxxx'}}
/>
</View>
);
}
通過html加載一個頁面
render() {
return (
<View style={styles.container}>
<WebView
ref={webView => this.webView = webView}
startInLoadingState={true}
onNavigationStateChange={e => this.onNavigationStateChange(e)}
source={{ html: '<h1'>Demo</h1>'}}
/>
</View>
);
}
二. RN WebView和H5之間的通信
1.RN WebView向H5頁面注入JS
思路: 通過jnjectedJavaScript的方式注入JS,在H5頁面加載之后立即執行。(可以理解為是在WebView中去主動觸發H5的方法,從而實現通信)
需要注意的是,injectedJavaScript注入的必須是JS,注入的內容可以是方法的實現也可以是方法名。其實注入函數名的時候,實際上注入的仍然是函數的實現。當注入js方法名需要傳遞參數的時候,可以提前將函數名作為字符串,函數參數作為變量,通過生成一個字符串然后再講字符串注入。
render() {
let text = 'back';
let call = `call('${text}')`;
return (
<View
style={{flex: 1, backgroundColor: 'white', marginBottom: SAFE_AREA_BOTTOM_HEIGHT}}>
<WebView style={{flex: 1}}
ref='webView'
injectedJavaScript={`${text1}`}
source={{
html: '<body>\n' +
'<button onClick="call()" style="margin-top: 100px;" id="call">call</button>\n' +
'<script>\n' +
' function call(text) {\n' +
' var btn= document.getElementById(\'call\')\n' +
' btn.innerHTML="text";\n' +
' }\n' +
'\n' +
'</script>\n' +
'</body>'
>
</WebView>
</View>
);
}
上述代碼當通過WebView向RN頁面注入一個html代碼的時候,通過injectedJavaScript向H5通信,然后更改button的名字。
2.WebView和H5相互發送監聽消息
該方式可以雙向發送消息
2.1 RN端向H5發送消息
WebView綁定ref,通過html5新增的postMessage發送消息
onLoadEnd={() => {
this.refs.webView.postMessage('RN向H5發送的消息');
}}
在H5中注冊監聽
window.onload = function() {
document.addEventListener('message', function(msg) {
console.log(msg)
message = msg.data;
});
}
2.2 H5向RN發送消息
在RN端通過onMessage接收消息
onMessage={(event) => {console.log(event.nativeEvent.data);}}
網頁端的 window.postMessage 只發送一個參數 data,此參數封裝在 RN 端的 event 對象中,即 event.nativeEvent.data。data 只能是一個字符串。
H5發送消息,此時只能傳遞string類型
window.postMessage('網頁向rn發送的消息');