国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

詳解react-native WebView 返回處理(非回調(diào)方法可解決)

來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 22:18:37
文檔

詳解react-native WebView 返回處理(非回調(diào)方法可解決)

詳解react-native WebView 返回處理(非回調(diào)方法可解決):1.前言 項目中有些頁面內(nèi)容是變更比較頻繁的,這些頁面我們會考慮用 網(wǎng)頁 來解決。 在RN項目中提供一個公用的Web頁,如果是網(wǎng)頁內(nèi)容,就跳轉(zhuǎn)到這個界面展示。 此時會有一個問題是,網(wǎng)頁會有一級頁面,二級頁面,這就會設(shè)計到導(dǎo)航欄返回鍵的處理(以及在And
推薦度:
導(dǎo)讀詳解react-native WebView 返回處理(非回調(diào)方法可解決):1.前言 項目中有些頁面內(nèi)容是變更比較頻繁的,這些頁面我們會考慮用 網(wǎng)頁 來解決。 在RN項目中提供一個公用的Web頁,如果是網(wǎng)頁內(nèi)容,就跳轉(zhuǎn)到這個界面展示。 此時會有一個問題是,網(wǎng)頁會有一級頁面,二級頁面,這就會設(shè)計到導(dǎo)航欄返回鍵的處理(以及在And

1.前言

項目中有些頁面內(nèi)容是變更比較頻繁的,這些頁面我們會考慮用 網(wǎng)頁 來解決。

在RN項目中提供一個公用的Web頁,如果是網(wǎng)頁內(nèi)容,就跳轉(zhuǎn)到這個界面展示。

此時會有一個問題是,網(wǎng)頁會有一級頁面,二級頁面,這就會設(shè)計到導(dǎo)航欄返回鍵的處理(以及在Android上返回鍵的處理)。

這個問題,在RN官網(wǎng)就可找到解決方式。就是用 onNavigationStateChange 這個回調(diào)方法記錄當(dāng)前的導(dǎo)航狀態(tài),從而判斷是返回上一級頁面還是退出這個網(wǎng)頁,回到App的其他界面。

但是,當(dāng)網(wǎng)頁的實現(xiàn)是React時,就會有問題了,你會發(fā)現(xiàn),當(dāng)頁面跳轉(zhuǎn)的時候,onNavigationStateChange這個回調(diào)方法沒有回調(diào)!!!怎么肥四!!

一開始嘗試了把網(wǎng)頁地址換成百度的,可以接收回調(diào),一切都運行的很好,可是換成我們的鏈接就不行,所以就把鍋甩給了后臺,以為是React哪邊寫的不對。

因為上一個項目時間緊,沒有時間好好去看一下源碼,就想了一個不是很完善的解決方案,就是網(wǎng)頁用js來回調(diào)App來告知現(xiàn)在的導(dǎo)航狀態(tài),這樣的解決方式顯示是不友好的。

現(xiàn)在稍微有點時間看了源碼才知道真正原因。

2.原因

下面就分析一下這個問題的原因和我的解決方式。

1.首先,先找到源碼的位置。

node_modules\react-native\ReactAndroid\src\main\java\com\facebook\react\views\webview

node_modules\react-native\Libraries\Components\WebView

目錄結(jié)構(gòu)是這樣的:

 

2.實現(xiàn)的代碼段 (JAVA端)

RN的實際運行代碼都是原生代碼,所以,像WebView組件的一些事件回調(diào),其實都是原生代碼中的回調(diào)觸發(fā)的。如下

(ReactWebViewManager.java) rn版本0.47.1

protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我們在寫Android原生代碼時,監(jiān)聽網(wǎng)頁加載情況使用的工具。
 protected static final String REACT_CLASS = "RCTWebView"; //定義的原生組件名,在后面JS中會對應(yīng)到。

 //...

 @Override
 public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回調(diào)方法,此處只舉一例
 super.onPageStarted(webView, url, favicon);
 mLastLoadFailed = false;

 dispatchEvent(
 webView,
 new TopLoadingStartEvent( //自己定義的時間,dispatch后,事件會傳給js
 webView.getId(),
 createWebViewEvent(webView, url)));
 }

 //...
 }

(ReactWebViewManager.java) rn版本0.43.3  ,RN不同版本會有代碼調(diào)整,所以RN升級的時候,需要仔細(xì)的回歸測試。

protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我們在寫Android原生代碼時,監(jiān)聽網(wǎng)頁加載情況使用的工具。
 protected static final String REACT_CLASS = "RCTWebView"; //定義的原生組件名,在后面JS中會對應(yīng)到。

 //...

 @Override
 public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回調(diào)方法,此處只舉一例
 super.onPageStarted(webView, url, favicon);
 mLastLoadFailed = false;

 dispatchEvent(
 webView,
 new TopLoadingStartEvent( //自己定義的時間,dispatch后,事件會傳給js
 webView.getId(),
 createWebViewEvent(webView, url)));
 }

 @Override
 public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) { //坑在這,這里就是導(dǎo)航有變化的時候會回調(diào)在這個版本是有這個處理的,但是不知道在哪個版本刪掉了 -.-
 super.doUpdateVisitedHistory(webView, url, isReload);

 dispatchEvent(
 webView,
 new TopLoadingStartEvent(
 webView.getId(),
 createWebViewEvent(webView, url)));
 }

 //...
 }

(TopLoadingStartEvent.java) 回調(diào)JS的Event

public class TopLoadingStartEvent extends Event<TopLoadingStartEvent> {
 public static final String EVENT_NAME = "topLoadingStart"; //對應(yīng)方法是onLoadingStart, 因為對RN的結(jié)構(gòu)不熟悉,在此處花了很長時間研究是怎么對應(yīng)的,最后找到了定義對應(yīng)的文件
 private WritableMap mEventData;

 public TopLoadingStartEvent(int viewId, WritableMap eventData) {
 super(viewId);
 mEventData = eventData;
 }

 @Override
 public String getEventName() {
 return EVENT_NAME;
 }

 @Override
 public boolean canCoalesce() {
 return false;
 }

 @Override
 public short getCoalescingKey() {
 // All events for a given view can be coalesced.
 return 0;
 }

 @Override
 public void dispatch(RCTEventEmitter rctEventEmitter) {
 rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData);
 }
}

(node_modules\react-native\ReactAndroid\src\main\java\com\facebook\react\uimanager\UIManagerModuleConstants.java)

這個文件里,定義了對應(yīng)關(guān)系

/**
 * Constants exposed to JS from {@link UIManagerModule}.
 */
/* package */ class UIManagerModuleConstants {

 /* package */ static Map getDirectEventTypeConstants() {
 return MapBuilder.builder()
 .put("topContentSizeChange", MapBuilder.of("registrationName", "onContentSizeChange"))
 .put("topLayout", MapBuilder.of("registrationName", "onLayout"))
 .put("topLoadingError", MapBuilder.of("registrationName", "onLoadingError"))
 .put("topLoadingFinish", MapBuilder.of("registrationName", "onLoadingFinish"))
 .put("topLoadingStart", MapBuilder.of("registrationName", "onLoadingStart"))
 .put("topSelectionChange", MapBuilder.of("registrationName", "onSelectionChange"))
 .put("topMessage", MapBuilder.of("registrationName", "onMessage"))
 .build();
 }
}

3.實現(xiàn)的代碼段 (JS端)

(node_modules\react-native\Libraries\Components\WebView\WebView.android.js)

在下面的代碼中可以看到只有 onLoadingStart    和 onLoadingFinish 才會調(diào)用  updateNavigationState ,問題就出現(xiàn)在這了,由于我們的網(wǎng)頁實現(xiàn)是React,只有一個頁面啊!所以只會調(diào)用一次 onLoadingStart  和 onLoadingFinish 。再點擊詳情頁并不會跳轉(zhuǎn)到新頁面,而是刷新原來的頁面。所以也就沒有 updateNavigationState 回調(diào)了。

class WebView extends React.Component {
 static propTypes = { //給外部定義的可設(shè)置的屬性
 ...ViewPropTypes,
 renderError: PropTypes.func,
 renderLoading: PropTypes.func,
 onLoad: PropTypes.func,
 //...
 }

 render() { //繪制頁面內(nèi)容
 //...
 var webView =
 <RCTWebView
 ref={RCT_WEBVIEW_REF}
 key="webViewKey"
 style={webViewStyles}
 source={resolveAssetSource(source)}
 onLoadingStart={this.onLoadingStart}
 onLoadingFinish={this.onLoadingFinish}
 onLoadingError={this.onLoadingError}/>;

 return (
 <View style={styles.container}>
 {webView}
 {otherView}
 </View>
 );
 }

 onLoadingStart = (event) => {
 var onLoadStart = this.props.onLoadStart;
 onLoadStart && onLoadStart(event);
 this.updateNavigationState(event);
 };

 onLoadingFinish = (event) => {
 var {onLoad, onLoadEnd} = this.props;
 onLoad && onLoad(event);
 onLoadEnd && onLoadEnd(event);
 this.setState({
 viewState: WebViewState.IDLE,
 });
 this.updateNavigationState(event);
 };

 updateNavigationState = (event) => {
 if (this.props.onNavigationStateChange) {
 this.props.onNavigationStateChange(event.nativeEvent);
 }
 };
}

var RCTWebView = requireNativeComponent('RCTWebView', WebView, { //對應(yīng)上面JAVA中的 ‘RCTWebView'
 nativeOnly: { messagingEnabled: PropTypes.bool, }, });


 module.exports = WebView; 

2.解決方法

既然原因找到了,就容易解決了

解決方式:自定義WebView,添加 doUpdateVisitedHistory 處理,在每次導(dǎo)航變化的時候,通知JS。

1. 拷貝下圖中的文件到我們自己項目中的Android代碼目錄下

拷貝完后的Android目錄:

ReactWebViewManager.java中需要修改幾個地方

public class ReactWebViewManager extends SimpleViewManager<WebView> {
 protected static final String REACT_CLASS = "RCTWebView1"; //此處修改一下名字

 protected static class ReactWebViewClient extends WebViewClient {
 @Override
 public void doUpdateVisitedHistory(WebView webView, String url, boolean isReload) {
 super.doUpdateVisitedHistory(webView, url, isReload);

 dispatchEvent( //在導(dǎo)航變化的時候,dispatchEvent
 webView,
 new TopCanGoBackEvent(
 webView.getId(),
 createCanGoBackWebViewEvent(webView, url)));
 }
 }
}

TopCanGoBackEvent是我自己添加的一個Event,專門用來通知導(dǎo)航變化

TopCanGoBackEvent.java

public class TopCanGoBackEvent extends Event<TopCanGoBackEvent> {

 public static final String EVENT_NAME = "topChange"; 
 private WritableMap mEventData;

 public TopCanGoBackEvent(int viewId, WritableMap eventData) {
 super(viewId);
 mEventData = eventData;
 }

 @Override
 public String getEventName() {
 return EVENT_NAME;
 }

 @Override
 public boolean canCoalesce() {
 return false;
 }

 @Override
 public short getCoalescingKey() {
 // All events for a given view can be coalesced.
 return 0;
 }

 @Override
 public void dispatch(RCTEventEmitter rctEventEmitter) {
 rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData);
 }
}

新建 ReactWebViewPage.java

public class ReactWebViewPackage implements ReactPackage {

 @Override
 public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {

 return Collections.emptyList();
 }

 @Override
 public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
 return Arrays.<ViewManager>asList(
 new ReactWebViewManager()
 );
 }
}

然后在MainApplication中添加這個模塊

public class MainApplication extends Application implements ReactApplication {
 @Override
 protected List<ReactPackage> getPackages() {
 return Arrays.<ReactPackage>asList(
 new MainReactPackage(),
 new ReactWebViewPackage() //WebView
 );
 }
}

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

詳解react-native WebView 返回處理(非回調(diào)方法可解決)

詳解react-native WebView 返回處理(非回調(diào)方法可解決):1.前言 項目中有些頁面內(nèi)容是變更比較頻繁的,這些頁面我們會考慮用 網(wǎng)頁 來解決。 在RN項目中提供一個公用的Web頁,如果是網(wǎng)頁內(nèi)容,就跳轉(zhuǎn)到這個界面展示。 此時會有一個問題是,網(wǎng)頁會有一級頁面,二級頁面,這就會設(shè)計到導(dǎo)航欄返回鍵的處理(以及在And
推薦度:
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 成人久久精品一区二区三区 | 激情一区二区三区成人 | 国产乱来视频 | 亚洲日韩欧美视频 | 午夜大片网 | 日韩一级精品久久久久 | 久久国产综合精品欧美 | 中文国产成人精品久久久 | 国产高清一区二区三区 | 色在线播放 | 国产区精品在线 | 亚洲欧洲精品成人久久曰影片 | 久久免费福利视频 | 欧美福利在线观看 | 亚洲国产精品一区二区久久 | 精品久久久久久综合网 | 国产日韩欧美在线观看不卡 | 国产精品欧美一区二区三区 | 香蕉视频你懂的 | 日韩中文在线观看 | 国产三级网站在线观看 | 另类第一页 | 久久精品99久久香蕉国产色戒 | 精品一区二区三区四区五区 | 欧美自拍亚洲 | 亚洲视频一区二区 | 日韩欧美高清一区 | 97伊人网| 国产特黄 | 一区二区三区免费在线 | 欧美 日韩 亚洲另类专区 | 欧美交性又色又爽又黄 | 亚洲va欧美ⅴa国产va影院 | 在线播放真实国产乱子伦 | 亚洲欧洲综合在线 | 久久久久国产精品 | 欧美aⅴ在线 | 一区二区三区四区电影 | 欧美性一区二区三区五区 | 日韩电影中文字幕在线网站 | 久久国产精品高清一区二区三区 |