image.png
一、安装
需要使用第三方的的webview组件
yarn add react-native-webview@11.4.5
- 深坑:在安装11.6.1以上版本时,遇到
错误: 已在类 RNCWebChromeClient中定义了方法 onPermissionRequest(PermissionRequest)
,在github的Issues中:https://github.com/react-native-webview/react-native-webview/issues/2001 找到答案:安装11.4.5的版本,问题得到了解决。
- 2021.5.25日,版本升级到11.6.2,以上问题得到了解决,但并没有完全得到验证!!!
- 注意:在安装后第一次启动时,需要下载相关的jar文件,可能需要等待较长的时间。
- 贴出package.json:
{
"name": "Rn0523b",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"react": "17.0.1",
"react-native": "0.64.1",
"react-native-webview": "11.4.5"
},
"devDependencies": {
"@babel/core": "^7.12.9",
"@babel/runtime": "^7.12.5",
"@react-native-community/eslint-config": "^2.0.0",
"babel-jest": "^26.6.3",
"eslint": "7.14.0",
"jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.64.0",
"react-test-renderer": "17.0.1"
},
"jest": {
"preset": "react-native"
}
}
二、一次完整的Web与Rn的通信:
1. 网页(./htdocs/index.html)
<!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>
<link rel="stylesheet" href="main.css"/>
</head>
<body>
<marquee>
<h1>marquee实现的跑马灯</h1>
</marquee>
<input class="info" name="uname" value="John"/>
<br>
<button class="info">发送给原生组件</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>
2. ./htdocs/main.css
.info{
font-size: 30px;
line-height: 2em;
width: 300px;
}
- 以上两文件可以放在各处,见文章底部说明。
- 我们以后台服务为例:
json-server htdocs/users.json -s htdocs --host 0.0.0.0
3、React Native的代码
App.js
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中的发送。。'}
_changeColor=()=>{
this.wv.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 script=`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.wv=ref} injectedJavaScript={script} source={{uri:"http://172.16.50.48:3000/index.html"}}/>
</View>
)
}
}
const styles = StyleSheet.create({})
附:html的引入不同方式
<WebView
//不同的source情况
// source={{ uri: 'http://johnyu.cn' }}
// source={{ html: '<h1>Hello world</h1>' }}
// source={require('./index.html')} //此方式不会进行html解析
//文件位于android/src/main/assets/下
source={{uri:'file:///android_asset/index.html'}}
injectedJavaScript={runFirst}
onMessage={(this._receive)}
/>