javascript - react-native-webview 的 stopLoading 方法会导致网站冻结
我想在 react-native 的 webview 中拦截链接的点击,并执行自定义操作,而不是像官方指南中描述的那样跳转到链接目标。以下是我的做法:
import React from 'react';
import {View, Linking} from 'react-native';
import AsyncStorage from '@react-native-community/async-storage';
import {WebView} from 'react-native-webview';
export default class WebViewScreen extends React.Component {
static navigationOptions = {
title: 'Produck',
};
constructor(props) {
super(props);
}
/**
* Defines content and look of the WebViewScreen.
*/
render() {
const DEFAULT_URL = "https://www.myurl.de/index.html";
return (
<View style={{ flex: 1 }}>
<WebView
ref = {webview => {
this.myWebView = webview;
}}
renderLoading = {this.renderLoading}
startInLoadingState = {true}
automaticallyAdjustContentInsets = {true}
source = {{ uri: DEFAULT_URL }}
javaScriptEnabled = {true}
domStorageEnabled = {true}
cacheEnabled = {false}
useWebKit = {true} // use WKWebView on iOS (http://facebook.github.io/react-native/blog/2018/08/27/wkwebview)
onNavigationStateChange={this.handleWebViewNavigationStateChange.bind(this)}
/>
</View>
);
}
handleWebViewNavigationStateChange = newNavState => {
const {url} = newNavState;
if (!url) return;
if (isExternal(url)) {
this.myWebView.stopLoading();
// do something else, e.g.
Linking.openURL(url);
}
};
}
如果我点击该 WebView 中的一个链接,URL 会按预期在系统的浏览器中打开。然而问题是,之后 WebView 会被冻结。我无法再点击任何链接,甚至无法滚动页面。当然,这不是正常状态。关键是希望在其他地方打开链接,以便 WebView 中的页面仍然可用。即使我删除 Linking 部分,结果也会保持不变。然后页面在点击链接时就会冻结。
有人知道该怎么办吗?我猜stopLoading方法不仅仅是中止加载。它是否也可能取消当前页面上正在运行的任何Javascript?如果是这样,我可以防止吗?
答案#1
至少在我的情况下,我已经找到了一个解决方案,这要归功于这个 pull request。我没有使用 onNavigationStateChange 和 stopLoading,而是转向了 onShouldStartLoadWithRequest。在这个事件的回调方法中,你可以定义是否应该放弃该请求,就当前的 webview 来说,只需返回 false 或 true 就可以。所以你会得到类似这样的代码:
render() {
...
return(...
<WebView
...
onShouldStartLoadWithRequest={this.handleWebViewRequest.bind(this)}
...
/>
);
}
handleWebViewRequest = request => {
const {url} = request;
if (!url) return false;
if (isExternal(url)) {
Linking.openURL(url);
return false;
} else {
return true;
}
}
到目前为止,就是“该做什么”部分。嗯,我也想回答我的其他问题,所以深入研究了 react-native-webview 的代码(一点也不好玩……评论呢? -> ‘让代码自己说明’ -> 嗯,它没有说明)。经过一段时间在不同的委托目标之间跳转后,stopLoading 调用似乎最终被交给了原生 WebView。所以在 Android 和 iOS 上的行为可能完全不同(我目前只开发 Android)。至于整个问题中的“我能阻止吗”部分,我可以说:“不能”。 当然,最有趣的部分应该是“stopLoading究竟做什么?我在某处读到它可以阻止当前页面上的链接被点击,确实如此。但那只是一种未经证实的说法。当我查阅原生 Android-WebView 文档时,我找到了非常非常好的解释:“停止当前加载。”(去谷歌一下,耶)。之后我就完全失去了深入挖掘的动力。嗯,除非有人比我更有见识,能提出更详细的解释,否则我可能会接受我自己的答案,至少它是我所遇到的开发问题的一个解决方案。
