React?Native?加載H5頁面的實現(xiàn)方法
一、基本使用
作為目前流行的移動跨平臺開發(fā)技術(shù),React Native 提供了一個使用 JavaScript 構(gòu)建原生跨平臺移動應(yīng)用的強大框架。使用React Native開發(fā)時,經(jīng)常會遇到加載H5網(wǎng)頁的需求,此時需要用到react-native-webview插件來執(zhí)行H5網(wǎng)頁的加載。
使用插件之前,需要先安裝npm i react-native-webview插件,命令如下:
npm i react-native-webview
然后,就可以在業(yè)務(wù)代碼中引入react-native-webview 插件的WebView組件,比如:
<WebView ref={ (webView) => this.webView = webView }
originWhitelist={ ['*'] }
// 布爾值,指定WebView中是否啟用JavaScript。只在Android上使用,因為在iOS上默認(rèn)啟用了JavaScript。
javaScriptEnabled={ true }
// 布爾值,指定是否開啟DOM本地存儲
domStorageEnabled={ true }
// 允許文件上傳
allowFileAccess={ true }
// 在webView內(nèi)部網(wǎng)頁中,調(diào)用window.postMessage可以觸發(fā)此屬性對應(yīng)的函數(shù),通過event.nativeEvent.data獲取接收到的數(shù)據(jù),實現(xiàn)網(wǎng)頁和RN之間的數(shù)據(jù)傳遞
onMessage={ this._onMessage }
//初始化調(diào)用方法
onLoad={() => { this.handleInjectJavascript();}}
// 加載時強制使用loading轉(zhuǎn)圈視圖,如果為true,webview可能會加載失敗,顯示為空白
startInLoadingState={false}
// webview加載錯誤頁面
renderError={this.renderErrorView}
// 網(wǎng)絡(luò)路徑
// 也可以為本地路徑 source={ {uri: 'http://192.168.1.1111:8080/'} }
source={ {uri: 'http://www.baidu.com/'} } />使用WebView組件加載H5頁面時,必然會涉及到交互。
1.1 RN向H5發(fā)送數(shù)據(jù)
如果是RN向H5發(fā)送數(shù)據(jù),那么可以調(diào)用onLoad函數(shù)的handleInjectJavascript() 方法。
//RN webview 向 vue發(fā)送數(shù)據(jù)
handleInjectJavascript = (data) => {
// 拼接數(shù)據(jù)為方法
const injectJavascriptStr = `(function() {
window.WebViewBridge.onMessage(${JSON.stringify(data)});
})()`;
// 通過 injectJavaScript 將數(shù)據(jù)傳遞給WebView頁面,并立即執(zhí)行為js
if(this.webView) {
this.webView.injectJavaScript(injectJavascriptStr)
}
}如果有回調(diào)的結(jié)果,需要在mounted生命周期函數(shù)中,
mounted() {
window.WebViewBridge = {
onMessage: this._onMessage //在window上掛載一個onMessage方法,RN會調(diào)用
}
// 自定義事件后直接觸發(fā):
const event = new Event('WebViewBridge')
window.dispatchEvent(event);
},
methods: {
// 接收 RN 發(fā)送的消息
_onMessage(data) {
let that = this;
console.log('data ------- ',JSON.stringify(data)); // 'hello world'
}
}
以上就是RN向H5 傳值的過程,其具體過程:RN中給 window.WebViewBridge 增加一個名為 onMessage 的方法,H5初始化頁面會對應(yīng)給出onMessage 指向的方法,在此代碼塊 指向 _onMessage 方法并執(zhí)行。
1.2 H5向RN傳遞數(shù)據(jù)
如果是H5頁面主動向RN發(fā)送數(shù)據(jù),需要用到postMessage方法。
mounted() {
// 自定義事件后直接觸發(fā):
const event = new Event('WebViewBridge');
window.dispatchEvent(event);
},
methods: {
// 向rn發(fā)送消息, 將值 'hello world' 掛載到 postMessage
_postMessage('hello world') {
window.ReactNativeWebView.postMessage(data);
}
}
RN 頁面在接收到 vue 傳輸?shù)臄?shù)據(jù)之后執(zhí)行 onMessage 函數(shù)方法。
onMessage={ this._onMessage }
_onMessage = (event) => {
console.log('接收vue發(fā)來的消息onMessage', event.nativeEvent.data);
}1.3 雙向傳值
當(dāng)然,有時候,也會涉及到多次雙向傳遞的情況。
mounted() {
window.WebViewBridge = {
onMessage: this._onMessage,
receiveMessage: this._receiveMessage //在window上掛載一個receiveMessage方法,RN自行調(diào)用
}
const event = new Event('WebViewBridge')
window.dispatchEvent(event);
},
methods: {
// 向rn發(fā)送消息
_postMessage('wow,RN!!') {
window.ReactNativeWebView.postMessage(data); // 將值 'wow,RN!!' 掛載到 postMessage
},
// 二次或多次接收RN發(fā)送消息
_receiveMessage(data){
let that = this;
console.log('data receiveMessage------- ',JSON.stringify(data));
}
}RN 頁面在接收到 H5 傳輸?shù)臄?shù)據(jù)之后執(zhí)行 onMessage 函數(shù)。
onMessage={ this._onMessage }
// 接受H5發(fā)送來的消息
_onMessage = (event) => {
console.log('接收H5發(fā)來的消息onMessage', event.nativeEvent.data);
const injectJavascriptStr = `(function() {
window.WebViewBridge.receiveMessage(${JSON.stringify('hello,vue2!!! ')});
})()`;
this.webView.injectJavaScript(injectJavascriptStr);
}二、屬性和方法
使用 WebView 組件我們可以通過 url 來加載顯示一個網(wǎng)頁,也可以傳入一段 html 代碼來顯示。該組件的引入是解決 React Native 內(nèi)嵌 H5 的比較好的解決方案,該組件自帶的常用屬性和方法我們可以歸納如下:
2.1 屬性
- source:在 WebView 中載入一段靜態(tài)的 html 代碼或是一個 url(還可以附帶一些 header 選項)
- automaticallyAdjustContentInsets:設(shè)置是否自動調(diào)整內(nèi)容。格式:boolean
- contentInset:設(shè)置內(nèi)容所占的尺寸大小。格式為{top:number,left:number,bottom:number,right:number}
- injectJavaScript:當(dāng)網(wǎng)頁加載之前注入一段 js 代碼。其值是字符串形式。
- startInLoadingState:是否開啟頁面加載的狀態(tài),其值為 true 或者 false。
- bounces(僅iOS):回彈特性。默認(rèn)為 true。如果設(shè)置為 false,則內(nèi)容拉到底部或者頭部都不回彈。
- scalesPageToFit(僅iOS):用于設(shè)置網(wǎng)頁是否縮放自適應(yīng)到整個屏幕視圖,以及用戶是否可以改變縮放頁面。
- scrollEnabled(僅iOS):用于設(shè)置是否開啟頁面滾動。
- domStorageEnabled(僅Android):用于控制是否開啟 DOM Storage(存儲)。
- javaScriptEnabled(僅Android):是否開啟 JavaScript,在 iOS 中的 WebView 是默認(rèn)開啟的。
2.2 方法
- onNavigationStateChange:當(dāng)導(dǎo)航狀態(tài)發(fā)生變化的時候調(diào)用。
- onLoadStart:當(dāng)網(wǎng)頁開始加載的時候調(diào)用。
- onError:當(dāng)網(wǎng)頁加載失敗的時候調(diào)用。
- onLoad:當(dāng)網(wǎng)頁加載結(jié)束的時候調(diào)用。
- onLoadEnd:當(dāng)網(wǎng)頁加載結(jié)束調(diào)用,不管是成功還是失敗。
- renderLoading:WebView組件正在渲染頁面時觸發(fā)的函數(shù),只有 startInLoadingState 為 true 時該函數(shù)才起作用。
- renderError:監(jiān)聽渲染頁面出錯的函數(shù)。
- onShouldStartLoadWithRequest(僅iOS):該方法允許攔截 WebView 加載的 URL 地址,進行自定義處理。該方法通過返回 true 或者 false 來決定是否繼續(xù)加載該攔截到請求。
三、使用示例
3.1 加載外源網(wǎng)頁信息
import React,{Component} from 'react'
import {
StyleSheet,
View,
Text,
WebView,
} from 'react-native'
export default class Root extends Component{
constructor(props){
super(props)
}
render(){
return (
<View style={styles.container}>
<WebView
source={{uri: 'https://www.baidu.com'}}
domStorageEnabled={true}
javaScriptEnabled={true}
startInLoadingState={true}
automaticallyAdjustContentInsets={true}>
</WebView>
</View>
)
}
}
const styles = StyleSheet.create({
container:{
flex:1,
},
})
上面是一個加載百度首頁的示例。
3.2 登陸場景
一款 toB 的 app,面對很多家客戶,每家客戶都有自己的登錄系統(tǒng)界面,并且客戶要求接入自己的登錄系統(tǒng)。這個時候就需要 webview 接入登錄界面之后,進行一些 “值攔截”,進行登錄狀態(tài)判斷。這里主要用到 webview 的 onNavigationStateChange 參數(shù)。此方法會在當(dāng)導(dǎo)航狀態(tài)發(fā)生變化的時候調(diào)用,例如取到下面的參數(shù):
{
"canGoBack": false,
"canGoForward": false,
"loading": true,
"navigationType": "other",
"target": 229,
"title": "",
"url": "https://www.baidu.com/"
}這里主要注意 url 字段,網(wǎng)頁內(nèi)部登錄完成之后,可以發(fā)起一個重定向,前端關(guān)注 url 變化,進行登錄狀態(tài)的判斷,同時重定向的 url 中可以拼接一些登錄信息字段,用于前端登錄狀態(tài)校驗等。
{ "url": "https://www.baidu.com ? sessionId=xxx & username= xxx" }3.3 功能模塊嵌入到 RN 中
將 webview 作為功能模塊載體,這個時候就會涉及到用戶交互,需要 rn 與 h5 進行值的互相傳遞。此時就要react native 向 web 中注入 js,web 也可以主動回傳數(shù)據(jù)到 react native中。webview 組件提供了 injectedJavaScript 用于向 h5 注入js,在 h5 中使用 window.ReactNativeWebView.postMessage 進行主動的回調(diào),并且在 webview 的 onMessage 中進行字段的監(jiān)聽,以此就可以完成 react 和 h5 之間的數(shù)據(jù)交互。
const injectJSStr = `
window.injectStr='我是注入的字段';
var div = document.getElementById('testID');
div.style.color='red';
div.style.fontSize='100px';
`;
const html = `
<html>
<head></head>
<body>
<script>
setTimeout(function () {
window.ReactNativeWebView.postMessage(window.injectStr)
}, 2000)
</script>
<div id='testID'>Hello Word</div>
</body>
</html>
`;
......
<View style={{flex: 1}}>
<WebView
source={{html}}
injectedJavaScript={injectJSStr}
onMessage={event => {
alert(event.nativeEvent.data);
}}
/>
</View>
3.4 完整示例
例如,有下面一個需求:RN里面通過觸發(fā)刷新使H5界面的背景色可以隨機改變;H5 界面我們寫一個簡單的 input 輸入使輸入的文字可以在RN 顯示出來。
import React, {Component} from 'react';
import {Text, StyleSheet, View, Button} from 'react-native';
import WebView from 'react-native-webview';
export default class App extends Component {
state = {colorIndex: 0, tip: '原生的Text組件,等webview中的發(fā)送。。'};
changeColor = () => {
this.webview.reload();
let colorIndex = this.state.colorIndex;
colorIndex = ++colorIndex % 5;
this.setState({colorIndex});
};
recieve = msg => {
let data = msg.nativeEvent.data;
let uname = JSON.parse(data).uname;
this.setState({tip: uname});
};
render() {
let colors = ['gray', 'yellow', 'red', 'antiquewhite', 'white'];
let scriptStr = `document.body.style.backgroundColor='${
colors[this.state.colorIndex]
}'`;
return (
<View style={{flex: 1}}>
<Button title="刷新WebView的背景色" onPress={this.changeColor} />
<Text style={{fontSize: 30}}>{this.state.tip}</Text>
<WebView
onMessage={this.recieve}
ref={ref => (this.webview = ref)}
injectedJavaScript={scriptStr}
source={{uri: 'http://192.168.180.241:8080/test.html'}}
/>
</View>
);
}
}
H5的代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input class="info" name="uname" value="John" />
<br>
<button class="info">發(fā)送給原生組件</button>
<script>
document.querySelector('button').addEventListener('click', () => {
let uname = document.querySelector('input[name="uname"]').value
let msg = JSON.stringify({
uname
})
window.ReactNativeWebView.postMessage(msg)
})
</script>
</body>
</html>到此這篇關(guān)于React Native 加載H5頁面的文章就介紹到這了,更多相關(guān)React Native H5頁面內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡易的redux?createStore手寫實現(xiàn)示例
這篇文章主要介紹了簡易的redux?createStore手寫實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-10-10
D3.js(v3)+react 實現(xiàn)帶坐標(biāo)與比例尺的散點圖 (V3版本)
散點圖(Scatter Chart),通常是一橫一豎兩個坐標(biāo)軸,數(shù)據(jù)是一組二維坐標(biāo),分別對應(yīng)兩個坐標(biāo)軸,與坐標(biāo)軸對應(yīng)的地方打上點。由此可以猜到,需要的元素包括circle(圓)和axis(坐標(biāo)軸),接下來通過本文大家分享D3.js(v3)+react 實現(xiàn)帶坐標(biāo)與比例尺的散點圖 (V3版本) ,一起看看2019-05-05
react?fiber使用的關(guān)鍵特性及執(zhí)行階段詳解
這篇文章主要為大家介紹了react?fiber使用的關(guān)鍵特性及執(zhí)行階段詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05
關(guān)于React動態(tài)加載路由處理的相關(guān)問題
這篇文章主要介紹了關(guān)于React動態(tài)加載路由處理的相關(guān)問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01
react組件從搭建腳手架到在npm發(fā)布的步驟實現(xiàn)
這篇文章主要介紹了react組件從搭建腳手架到在npm發(fā)布的步驟實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01

