文档地址:https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#communicating-between-js-and-native
WebView组件是RN端与Web端交互的一个常用组件。
原本WebView组件是放在react-native组件库当中的,现在RN把它从组件库当中移除了,放到了react-native-webview库当中。最近我在升级公司RN项目的app,在适配WebView组件当中遇到很多问题,特此记录一下,避免再次踩坑。
RN端与Web端的通信和交互方式有三种:
(1)React Native -> Web: The injectedJavaScript prop
(2)React Native -> Web: The injectJavaScript method
(3)Web -> React Native: The postMessage method and onMessage prop
- RN端注入JS脚本到Web端。
- 这是一个脚本,该脚本在首次加载网页后立即运行。
- 即使页面重新加载或导航离开,它也只能运行一次。
import React, { Component } from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
const runFirst = `
document.body.style.backgroundColor = 'red';
setTimeout(function() { window.alert('hi') }, 2000);
true; // note: this is required, or you'll sometimes get silent failures
`;
return (
);
}
}
- RN端注入JS脚本到Web端。
- 前面提到的injectedJavaScript道具的缺点是只能运行一次。
- 这就是为什么我们还在webview ref上公开了一个称为injectJavaScript的方法(请注意稍有不同的名称!)。
import React, { Component } from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
const run = `
document.body.style.backgroundColor = 'blue';
true;
`;
setTimeout(() => {
this.webref.injectJavaScript(run);
}, 3000);
return (
(this.webref = r)}
source={{
uri:
'https://github.com/react-native-community/react-native-webview',
}}
/>
);
}
}
注意:
在IOS平台,RN端往Web端传递事件和数据时。
- 注入脚本的复合参数(如数组或JSON对象)应当使用JSON.stringify(data)进行处理,否则Web端无法接收到正确的参数。
RN端要调动Web端的一个方法,并传递复合参数:
let jsCode = `if(${callback}){
var func = ${callback};
func && func(${JSON.stringify(response.data)});
}`;
webView.injectJavaScript(jsCode);
- RN端注入JS脚本到Web端。
- 这是在首次加载网页之前运行的脚本。
- 即使页面重新加载或导航离开,它也只能运行一次。 如果要在执行Web代码之前将任何内容注入到窗口,本地存储或文档中,这将很有用。
import React, { Component } from 'react';
import { View } from 'react-native';
import { WebView } from 'react-native-webview';
export default class App extends Component {
render() {
const runFirst = `
window.isNativeApp = true;
true; // note: this is required, or you'll sometimes get silent failures
`;
return (
);
}
}
- Web端往RN传递事件和数据可以通过window.ReactNativeWebView.postMessage(params)方法和WebView组件的onMessage属性来实现。
- Web端调用window.ReactNativeWebView.postMessage(params)方法,携带一个字符串参数,往RN传递数据。
- RN端通过onMessage来监听Web传递的事件和数据,然后进行处理。
- 我们必须设置onMessage或window.ReactNativeWebView.postMessage方法。
- window.ReactNativeWebView.postMessage仅接受一个参数,该参数必须是字符串。
注意:
react-native-webview库5.0.0版本之前,Web端是用window.postMessage(param)方法往RN端传递事件和数据的。
5.0.0版本后,就改成了 window.ReactNativeWebView.postMessage(param)。
如果想要在新版本兼容旧版本的web端代码,可以注入JS代码中加入下列代码:
const injectedJavascript = `(function() {
window.postMessage = function(data) {
window.ReactNativeWebView.postMessage(data);
};
})()`;
详情请参阅文档:https://github.com/react-native-community/react-native-webview/releases/tag/v5.0.0