[RN]用webview展示Vue单页面应用,跳转页面时,安卓不触发onNavigationStateChange方法
需求:在APP中使用WebView组件展示H5页面,在APP上自定义一个头部回退组件,点击返回按钮,如果H5页面有跳转则返回H5页面的上一页,如果没有跳转则退出当前的APP页面。原本的想法:通过WebView的onNavigationStateChange()方法监听H5页面的跳转,根据此时的canGoBack参数判断进行后续操作。<WebViewsource={{uri: url}}onN
需求:
在APP中使用WebView组件展示H5页面,在APP上自定义一个头部回退组件,点击返回按钮,如果H5页面有跳转则返回H5页面的上一页,如果没有跳转则退出当前的APP页面。
原本的想法:
通过WebView的onNavigationStateChange()方法监听H5页面的跳转,根据此时的canGoBack参数判断进行后续操作。
<WebView
source={{uri: url}}
onNavigationStateChange={navState => {
this.canGoBack = navState.canGoBack;
}}
/>
出现的问题:
在ios上没问题,在安卓第一次加载页面时能触发onNavigationStateChange,然而点击页面进行跳转时,没有触发。
原因猜测:
项目中使用的H5页面是用Vue写的,它是单页面应用程序(其实项目生成的是一个页面,所有组件都在这个页面中,它的路由跳转机制其实是在一个页面里通过锚点定位到相应位置的组件),所以页面跳转之后,因为机制,在安卓上无法监听到页面路径的变化。
解决方法一:
H5页面用window.open()进行跳转
解决方法二:
window.open()在有些浏览器上会被拦截,第二种方法是通过injectedJavaScript注入一些JavaScript来包装历史记录功能,以拦截这些哈希URL更改:
<WebView
source={{ uri: url }}
ref={ref => this.webView = ref}
injectedJavaScript={`
(function() {
function wrap(fn) {
return function wrapper() {
var res = fn.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
}
}
history.pushState = wrap(history.pushState);
history.replaceState = wrap(history.replaceState);
window.addEventListener('popstate', function() {
window.ReactNativeWebView.postMessage('navigationStateChange'); // web端向APP端发送消息
});
})();
true;
`}
onMessage={({ nativeEvent: state }) => { // App接受从 web端传来的消息
if (state.data === 'navigationStateChange') {
this.canGoBack = navState.canGoBack; // 这时记录下页面的可回退状态,然后通过ref获取该webview,调用它的goBack方法就可以了
}
}}
/>
这是react-native-webview官方给出的解决方法。
History是H5的API,是浏览器窗口的历史记录。
pushState 方法会增加一条历史记录,同时改变地址栏的地址内容,但并不会刷新页面(即页面实际上没有跳转)。
replaceState 方法会替换当前的历史记录,不刷新页面。
popstate 事件:历史记录发生改变时触发,调用history.pushState()或者history.replaceState()不会触发,只有用户点击浏览器倒退按钮和前进按钮,或者使用 JavaScript 调用History.back()、History.forward()、History.go()方法时才会触发。
hashchange 事件:当页面的hash值改变的时候触发,常用于构建单页面应用。
上面的代码用hashchange代替popstate也能实现
更多推荐
所有评论(0)