Rumah hujung hadapan web tutorial js 在react-native中通过WebView处理返回非回调方法

在react-native中通过WebView处理返回非回调方法

Jun 04, 2018 am 11:42 AM
react-native web webview

这篇文章主要介绍了详解react-native WebView 返回处理(非回调方法可解决),现在分享给大家,也给大家做个参考。

1.前言

项目中有些页面内容是变更比较频繁的,这些页面我们会考虑用 网页 来解决。

在RN项目中提供一个公用的Web页,如果是网页内容,就跳转到这个界面展示。

此时会有一个问题是,网页会有一级页面,二级页面,这就会设计到导航栏返回键的处理(以及在Android上返回键的处理)。

这个问题,在RN官网就可找到解决方式。就是用 onNavigationStateChange 这个回调方法记录当前的导航状态,从而判断是返回上一级页面还是退出这个网页,回到App的其他界面。

但是,当网页的实现是React时,就会有问题了,你会发现,当页面跳转的时候,onNavigationStateChange这个回调方法没有回调!!!怎么肥四!!

一开始尝试了把网页地址换成百度的,可以接收回调,一切都运行的很好,可是换成我们的链接就不行,所以就把锅甩给了后台,以为是React哪边写的不对。

因为上一个项目时间紧,没有时间好好去看一下源码,就想了一个不是很完善的解决方案,就是网页用js来回调App来告知现在的导航状态,这样的解决方式显示是不友好的。

现在稍微有点时间看了源码才知道真正原因。

2.原因

下面就分析一下这个问题的原因和我的解决方式。

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

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

node_modules\react-native\Libraries\Components\WebView

目录结构是这样的:

 

2.实现的代码段 (JAVA端)

RN的实际运行代码都是原生代码,所以,像WebView组件的一些事件回调,其实都是原生代码中的回调触发的。如下

(ReactWebViewManager.java) rn版本0.47.1

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)));
  }

  //...
 }
Salin selepas log masuk

(ReactWebViewManager.java) rn版本0.43.3 ,RN不同版本会有代码调整,所以RN升级的时候,需要仔细的回归测试。

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)));
  }

  //...
 }
Salin selepas log masuk

(TopLoadingStartEvent.java) 回调JS的Event

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);
 }
}
Salin selepas log masuk

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

这个文件里,定义了对应关系

/**
 * 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();
 }
}
Salin selepas log masuk

3.实现的代码段 (JS端)

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

在下面的代码中可以看到只有 onLoadingStart 和 onLoadingFinish 才会调用 updateNavigationState ,问题就出现在这了,由于我们的网页实现是React,只有一个页面啊!所以只会调用一次 onLoadingStart 和 onLoadingFinish 。再点击详情页并不会跳转到新页面,而是刷新原来的页面。所以也就没有 updateNavigationState 回调了。

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(&#39;RCTWebView&#39;, WebView, {  //对应上面JAVA中的 ‘RCTWebView&#39;
 nativeOnly: { messagingEnabled: PropTypes.bool, }, });


 module.exports = WebView;
Salin selepas log masuk

2.解决方法

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

解决方式:自定义WebView,添加 doUpdateVisitedHistory 处理,在每次导航变化的时候,通知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(    //在导航变化的时候,dispatchEvent
          webView,
          new TopCanGoBackEvent(
              webView.getId(),
              createCanGoBackWebViewEvent(webView, url)));
    }
 }
}
Salin selepas log masuk

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);
 }
}
Salin selepas log masuk

新建 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()
    );
  }
}
Salin selepas log masuk

然后在MainApplication中添加这个模块

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

以上就是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 = &#39;webview1&#39;; //此处需要修改名称

 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(&#39;RCTWebView1&#39;, CustomWebView, CustomWebView.extraNativeComponentConfig); //修改名称

module.exports = CustomWebView; //修改名称
Salin selepas log masuk

至此就完成自定义WebView模块。也可以解决网页是React实现,不能导航的问题。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

在vue中如何解决v-for使用报红并出现警告的问题(详细教程)

在Vuejs中如何实现搜索匹配功能方法(详细教程)

在vue.js中利用select下拉框实现绑定和取值方法

Atas ialah kandungan terperinci 在react-native中通过WebView处理返回非回调方法. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Cara menggunakan python+Flask untuk merealisasikan kemas kini masa nyata dan paparan log pada halaman web Cara menggunakan python+Flask untuk merealisasikan kemas kini masa nyata dan paparan log pada halaman web May 17, 2023 am 11:07 AM

1. Log keluaran ke fail menggunakan modul: pengelogan boleh menjana log peringkat tersuai, dan boleh mengeluarkan log ke laluan yang ditentukan Tahap log: nyahpepijat (log nyahpepijat) = 5) {clearTimeout (time) // Jika semua keputusan diperolehi 10. masa berturut-turut kosong Log mengosongkan tugas berjadual}return}if(data.log_type==2){//Jika log baharu diperolehi untuk(i=0;i

Paparkan kandungan web menggunakan komponen JavaFX WebView baharu dalam Java 13 Paparkan kandungan web menggunakan komponen JavaFX WebView baharu dalam Java 13 Aug 01, 2023 pm 01:09 PM

Gunakan komponen JavaFXWebView baharu dalam Java13 untuk memaparkan kandungan web Dengan pembangunan Java yang berterusan, JavaFX telah menjadi salah satu alat utama untuk membina antara muka grafik merentas platform. JavaFX menyediakan banyak perpustakaan grafik dan komponen, membolehkan pembangun membuat pelbagai antara muka pengguna dengan mudah. Antaranya, komponen JavaFXWebView adalah komponen yang sangat berguna yang membolehkan kami memaparkan kandungan web dalam aplikasi JavaFX. Di Java13, J

Cara menggunakan kedi pelayan web Nginx Cara menggunakan kedi pelayan web Nginx May 30, 2023 pm 12:19 PM

Pengenalan kepada Caddy Caddy ialah pelayan web yang berkuasa dan berskala tinggi yang pada masa ini mempunyai 38K+ bintang di Github. Caddy ditulis dalam bahasa Go dan boleh digunakan untuk pengehosan sumber statik dan proksi terbalik. Caddy mempunyai ciri-ciri utama berikut: Berbanding dengan konfigurasi kompleks Nginx, konfigurasi Caddyfile asalnya adalah sangat mudah secara dinamik melalui AdminAPI yang disediakannya, ia menyokong konfigurasi HTTPS automatik secara lalai, dan boleh memohon sijil HTTPS secara automatik; dan konfigurasikannya; ia boleh dikembangkan kepada data Berpuluh-puluh ribu tapak boleh dilaksanakan di mana-mana tanpa kebergantungan tambahan yang ditulis dalam bahasa Go, keselamatan memori lebih terjamin. Pertama sekali, kami memasangnya terus dalam CentO

Bagaimana untuk melaksanakan pengesahan borang untuk aplikasi web menggunakan Golang Bagaimana untuk melaksanakan pengesahan borang untuk aplikasi web menggunakan Golang Jun 24, 2023 am 09:08 AM

Pengesahan borang adalah pautan yang sangat penting dalam pembangunan aplikasi web Ia boleh menyemak kesahihan data sebelum menyerahkan data borang untuk mengelakkan kelemahan keselamatan dan ralat data dalam aplikasi. Pengesahan borang untuk aplikasi web boleh dilaksanakan dengan mudah menggunakan Golang Artikel ini akan memperkenalkan cara menggunakan Golang untuk melaksanakan pengesahan borang untuk aplikasi web. 1. Elemen asas pengesahan borang Sebelum memperkenalkan cara melaksanakan pengesahan borang, kita perlu mengetahui apakah elemen asas pengesahan borang. Unsur bentuk: unsur bentuk ialah

Menggunakan Jetty7 untuk pemprosesan pelayan Web dalam pembangunan API Java Menggunakan Jetty7 untuk pemprosesan pelayan Web dalam pembangunan API Java Jun 18, 2023 am 10:42 AM

Menggunakan Jetty7 untuk Pemprosesan Pelayan Web dalam Pembangunan JavaAPI Dengan pembangunan Internet, pelayan Web telah menjadi bahagian teras pembangunan aplikasi dan juga menjadi tumpuan banyak perusahaan. Untuk memenuhi keperluan perniagaan yang semakin meningkat, ramai pembangun memilih untuk menggunakan Jeti untuk pembangunan pelayan web, dan fleksibiliti dan skalabilitinya diiktiraf secara meluas. Artikel ini akan memperkenalkan cara menggunakan Jetty7 dalam pembangunan JavaAPI untuk We

Perlindungan masa nyata terhadap rentetan penyekat muka di web (berdasarkan pembelajaran mesin) Perlindungan masa nyata terhadap rentetan penyekat muka di web (berdasarkan pembelajaran mesin) Jun 10, 2023 pm 01:03 PM

Benteng penghalang muka bermakna sebilangan besar benteng terapung tanpa menyekat orang dalam video, menjadikannya kelihatan seperti terapung dari belakang orang itu. Pembelajaran mesin telah popular selama beberapa tahun, tetapi ramai orang tidak tahu bahawa keupayaan ini juga boleh dijalankan dalam penyemak imbas Artikel ini memperkenalkan proses pengoptimuman praktikal dalam rentetan video penyelesaian ini, dengan harapan dapat membukanya beberapa idea. mediapipeDemo (https://google.github.io/mediapipe/) menunjukkan prinsip pelaksanaan rentetan penyekat muka arus perdana atas permintaan sehingga pengiraan latar belakang pelayan video untuk mengekstrak kawasan potret dalam skrin video dan menukarnya kepada storan svg klien semasa memainkan video Muat turun svg dari pelayan dan gabungkannya dengan rentetan, potret

Apakah standard web? Apakah standard web? Oct 18, 2023 pm 05:24 PM

Piawaian web ialah satu set spesifikasi dan garis panduan yang dibangunkan oleh W3C dan organisasi lain yang berkaitan Ia termasuk penyeragaman HTML, CSS, JavaScript, DOM, kebolehcapaian Web dan pengoptimuman prestasi Dengan mengikut piawaian ini, keserasian halaman boleh dipertingkatkan. kebolehcapaian, kebolehselenggaraan dan prestasi. Matlamat standard web adalah untuk membolehkan kandungan web dipaparkan dan berinteraksi secara konsisten pada platform, pelayar dan peranti yang berbeza, memberikan pengalaman pengguna yang lebih baik dan kecekapan pembangunan.

Bagaimana untuk mengkonfigurasi nginx untuk memastikan bahawa pelayan frps dan web berkongsi port 80 Bagaimana untuk mengkonfigurasi nginx untuk memastikan bahawa pelayan frps dan web berkongsi port 80 Jun 03, 2023 am 08:19 AM

Pertama sekali, anda akan ragu-ragu, apakah itu frp? Ringkasnya, frp ialah alat penembusan intranet Selepas mengkonfigurasi klien, anda boleh mengakses intranet melalui pelayan. Sekarang pelayan saya telah menggunakan nginx sebagai laman web, dan hanya terdapat satu port 80. Jadi apakah yang perlu saya lakukan jika pelayan FRP juga mahu menggunakan port 80? Selepas membuat pertanyaan, ini boleh dicapai dengan menggunakan proksi terbalik nginx. Untuk menambah: frps ialah pelayan, frpc ialah pelanggan. Langkah 1: Ubah suai fail konfigurasi nginx.conf dalam pelayan dan tambahkan parameter berikut pada http{} dalam nginx.conf, server{listen80

See all articles