Heim > Web-Frontend > js-Tutorial > Hauptteil

So lösen Sie die Rückgabeverarbeitung von React-Native WebView, ohne es aufzurufen

php中世界最好的语言
Freigeben: 2018-03-17 13:32:04
Original
2170 Leute haben es durchsucht

Dieses Mal zeige ich Ihnen, wie Sie die Rückgabeverarbeitung von React-Native WebView ohne Aufruf lösen Ein praktischer Fall, werfen wir einen Blick darauf.

1. VorwortEs gibt einige Seiten im Projekt, die sich häufig ändern. Wir werden erwägen, Webseiten zu verwenden, um diese Seiten zu lösen.

Stellen Sie eine öffentliche Webseite im RN-Projekt bereit. Wenn es sich um Webinhalte handelt, springen Sie zur Anzeige zu dieser Schnittstelle.

Ein Problem derzeit besteht darin, dass die Webseite eine Seite der ersten Ebene und eine Seite der zweiten Ebene haben wird, die für die Handhabung der Eingabetaste der Navigationsleiste (sowie für die Verarbeitung der Return-Taste auf

Android

). Die Lösung für dieses Problem finden Sie auf der offiziellen RN-Website. Verwenden Sie einfach die Rückrufmethode onNavigationStateChange, um den aktuellen Navigationsstatus aufzuzeichnen, um zu bestimmen, ob Sie zur vorherigen Seite zurückkehren oder diese Webseite verlassen und zu anderen Schnittstellen der App zurückkehren möchten.

Wenn die Implementierung der Webseite jedoch React ist, tritt ein Problem auf. Wenn die Seite springt, hat die Rückrufmethode onNavigationStateChange keinen Rückruf! ! ! Wie fett! !

Zuerst habe ich versucht, die Webadresse auf die von Baidu zu ändern, die Rückrufe empfangen kann, aber es hat nicht funktioniert, wenn ich sie auf unseren Link geändert habe, also habe ich die Schuld dem gegeben Backend, ich dachte, es sei React. Welcher Teil ist falsch geschrieben.

Da das letzte Projekt knapp war und ich keine Zeit hatte, mir den Quellcode anzusehen, dachte ich über eine nicht sehr vollständige Lösung nach, nämlich die Verwendung von js auf der Webseite, um die App zurückzurufen Informieren Sie sich über den aktuellen Navigationsstatus. Die Anzeige ist unfreundlich.

Jetzt, da ich etwas Zeit hatte, den Quellcode zu lesen, kann ich den wahren Grund verstehen.

2. Gründe

Lassen Sie mich die Ursache dieses Problems und meine Lösung analysieren.

1. Suchen Sie zunächst den Speicherort des Quellcodes.

node_modulesreact-nativeReactAndroidsrcmainjavacomfacebookreactviewswebview

node_modulesreact-nativeLibrariesComponentsWebView

Die Verzeichnisstruktur

ist wie folgt:

2. Implementiertes Codesegment (JAVA-Seite)

Der tatsächlich laufende Code von RN ist nativer Code, also wie der WebView Komponente Einige der Ereignisrückrufe werden tatsächlich durch Rückrufe im nativen Code ausgelöst. Wie folgt

(ReactWebViewManager.java) rn Version 0.47.1

(ReactWebViewManager.java) rn Version 0.43.3, verschiedene Versionen von RN haben Codeanpassungen, also wenn RN Wird aktualisiert, erfordert sorgfältige Regressionstests.
protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我们在写Android原生代码时,监听网页加载情况使用的工具。
   protected static final String REACT_CLASS = "RCTWebView"; //定义的原生组件名,在后面JS中会对应到。
  //...
  @Override
  public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回调方法,此处只举一例
   super.onPageStarted(webView, url, favicon);
   mLastLoadFailed = false;
   dispatchEvent(
     webView,
     new TopLoadingStartEvent(   //自己定义的时间,dispatch后,事件会传给js
       webView.getId(),
       createWebViewEvent(webView, url)));
  }
  //...
 }
Nach dem Login kopieren

(TopLoadingStartEvent.java) Callback JS Event
protected static class ReactWebViewClient extends WebViewClient { //WebViewClient就是我们在写Android原生代码时,监听网页加载情况使用的工具。
   protected static final String REACT_CLASS = "RCTWebView"; //定义的原生组件名,在后面JS中会对应到。
  //...
  @Override
  public void onPageStarted(WebView webView, String url, Bitmap favicon) { //有很多回调方法,此处只举一例
   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) { //坑在这,这里就是导航有变化的时候会回调在这个版本是有这个处理的,但是不知道在哪个版本删掉了 -.-
   super.doUpdateVisitedHistory(webView, url, isReload);
   dispatchEvent(
     webView,
     new TopLoadingStartEvent(
       webView.getId(),
       createWebViewEvent(webView, url)));
  }
  //...
 }
Nach dem Login kopieren

(node_modulesreact-nativeReactAndroidsrcmainjavacomfacebookreactuimanagerUIManagerModuleConstants.java)
public class TopLoadingStartEvent extends Event<TopLoadingStartEvent> {
 public static final String EVENT_NAME = "topLoadingStart";  //对应方法是onLoadingStart, 因为对RN的结构不熟悉,在此处花了很长时间研究是怎么对应的,最后找到了定义对应的文件
 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);
 }
}
Nach dem Login kopieren

In dieser Datei ist die entsprechende Beziehung definiert

/**
 * 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();
 }
}
Nach dem Login kopieren
3. Implementiertes Code-Snippet (JS-Seite)

(node_modulesreact-nativeLibrariesComponentsWebViewWebView.android.js)

Im folgenden Code können Sie sehen Dass nur onLoadingStart und onLoadingFinish updateNavigationState aufrufen, tritt hier auf. Da unsere Webseite in React implementiert ist, gibt es nur eine Seite! Daher werden onLoadingStart und onLoadingFinish nur einmal aufgerufen. Durch erneutes Klicken auf die Detailseite wird nicht zu einer neuen Seite gesprungen, sondern die Originalseite wird aktualisiert. Es gibt also keinen updateNavigationState-Rückruf.

class WebView extends React.Component {
 static propTypes = {  //给外部定义的可设置的属性
  ...ViewPropTypes,
  renderError: PropTypes.func,
  renderLoading: PropTypes.func,
  onLoad: PropTypes.func,
  //...
  }
 render() { //绘制页面内容
  //...
  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, {  //对应上面JAVA中的 ‘RCTWebView'
 nativeOnly: { messagingEnabled: PropTypes.bool, }, });
 module.exports = WebView;
Nach dem Login kopieren
2. Lösung

Nachdem die Ursache gefunden wurde, ist es einfach, sie zu beheben.

Lösung: Passen Sie WebView an und fügen Sie die doUpdateVisitedHistory-Verarbeitung hinzu , benachrichtigen Sie JS jedes Mal, wenn sich die Navigation ändert.

1. Kopieren Sie die Dateien im Bild unten in das Android-Codeverzeichnis in unserem eigenen Projekt

拷贝完后的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(    //在导航变化的时候,dispatchEvent
          webView,
          new TopCanGoBackEvent(
              webView.getId(),
              createCanGoBackWebViewEvent(webView, url)));
    }
 }
}
Nach dem Login kopieren

TopCanGoBackEvent是我自己添加的一个Event,专门用来通知导航变化

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);
 }
}
Nach dem Login kopieren

新建 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()
    );
  }
}
Nach dem Login kopieren

然后在MainApplication中添加这个模块

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

以上就是Android需要修改的地方,ios我没有尝试过,应该大差不差同一个道理。

2. 拷贝下图中的文件到我们自己项目中的JS代码目录下,并修改一下名字

JS代码目录:

CustomWebView.android.js 有几个地方需要修改。

/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule CustomWebView  //此处需要修改名称
 */
var RCT_WEBVIEW_REF = 'webview1'; //此处需要修改名称
 render() {
  var webView =
   <NativeWebView
    onLoadingStart={this.onLoadingStart}
    onLoadingFinish={this.onLoadingFinish}
    onLoadingError={this.onLoadingError}
    onChange={this.onChange} //添加方法
   />;
  return (
   <View style={styles.container}>
    {webView}
    {otherView}
   </View>
  );
 }
 onChange = (event) => {  //添加方法
  this.updateNavigationState(event);
 };
}
var RCTWebView = requireNativeComponent('RCTWebView1', CustomWebView, CustomWebView.extraNativeComponentConfig); //修改名称
module.exports = CustomWebView; //修改名称
Nach dem Login kopieren

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

JS怎样操作改变radio的状态

JS脚本加载后再执行相应回调函数的操作

Das obige ist der detaillierte Inhalt vonSo lösen Sie die Rückgabeverarbeitung von React-Native WebView, ohne es aufzurufen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!