我如何返回 webview?我在 react-native 中使用 react-navigation 包 [英] How do I go back in webview? I am using the react-navigation package in react-native

查看:61
本文介绍了我如何返回 webview?我在 react-native 中使用 react-navigation 包的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 react-native 中安装了 react-navigation

I installed the react-navigation package in react-native

我已经实现了标签导航,其中之一以 webview 格式实现.

I have implemented tab navigation and one of them is implemented in webview format.

我的问题是,如果我按下 Android 上的后退物理按钮,我会从应用程序本身转到上一个选项卡,而不是从网络视图返回.

My problem is that if I press the back physical button on Android, I go from the app itself to the previous tab, not back from the webview.

我已经在互联网上为 webview 应用了后退按钮,但我还没有这样做.

I've already applied the back button for the webview on the internet, but I have not done that.

我尝试在调试时显示 onNavigationStateChange 日志,但是在第一次启动加载后移动 url 时它没有更新.这是我实现的代码:

I tried to display the onNavigationStateChange log when debugging, but it was not updated when url was moved after it was loaded at first startup. Here is the code I implemented:

import React from "react";
import {BackHandler} from "react-native";
import {WebView} from "react-native-webview";

class SermonScreen extends React.Component {
    constructor(props) {
        super(props);
    }
    static navigationOptions = {
        header: null
    };

    componentDidMount() {
        BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
    }

    componentWillUnmount() {
        BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
    }

    _onNavigationStateChange(navState) {
        console.log(navState);
        this.setState({
            canGoBack: navState.canGoBack
        });
    }

    handleBackButton = () => {
        console.log(this.state);
        if (this.state.canGoBack === true) {
            this.webView.goBack();
            return true;
        } else {
            return false;
        }
    };

    render() {
        return (
            <WebView
                source={{uri: 'https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos' }}
                ref={(webView) => this.webView = webView}
                onNavigationStateChange={this._onNavigationStateChange.bind(this)}
            />
        );
    }
}

export default SermonScreen;

推荐答案

按照官方 webview 文档,您可以尝试这样做:https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes

Following the official webview documnentation you could try to do this: https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes

一般来说,你差不多就到了,但是 YT 导航的工作方式使得无法通过 onNavigationStateChange 被捕获,这就是为什么我们注入一个 JS 代码来拦截这些哈希更改并发布消息到父组件,然后我们在 onMessage 处理程序中捕获它并正确设置状态变量.将 injectedJavaScriptonMessage 属性复制到您的示例中应该可以解决您的问题.

In general you were almost there, however the way the YT navigation works made it impossible to be caught via the onNavigationStateChange, that's why we inject a JS code that intercepts these hash changes and posts a message to the parent component, we then catch it inside the onMessage handler and set the state variable properly. Copying the injectedJavaScript and onMessage properties to your example should solve your problem.

我为您准备了一个组件,它似乎可以满足您的需求:

I prepared a component for you that seems to do what is needed:

 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
 */

import React, { Fragment } from "react";
import {
  SafeAreaView,
  StyleSheet,
  ScrollView,
  View,
  Text,
  BackHandler,
  StatusBar
} from "react-native";
import { WebView } from "react-native-webview";
import {
  Header,
  LearnMoreLinks,
  Colors,
  DebugInstructions,
  ReloadInstructions
} from "react-native/Libraries/NewAppScreen";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.startingUrl =
      "https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos";
    this.handleBackButton = this.handleBackButton.bind(this);
  }

  componentDidMount() {
    BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
  }

  componentWillUnmount() {
    BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
  }

  handleBackButton = () => {
    console.log(this.state);
    const { canGoBack } = this.state;
    if (canGoBack) {
      this.webView.goBack();
      return true;
    } else {
      return false;
    }
  };

  render() {
    return (
      <Fragment>
        <WebView
          source={{ uri: this.startingUrl }}
          style={{ marginTop: 20 }}
          ref={webView => (this.webView = webView)}
          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');
            });
          })();

          true;
        `}
          onMessage={({ nativeEvent: state }) => {
            if (state.data === "navigationStateChange") {
              // Navigation state updated, can check state.canGoBack, etc.
              this.setState({
                canGoBack: state.canGoBack
              });
            }
          }}
        />
      </Fragment>
    );
  }
}

export default App;

这篇关于我如何返回 webview?我在 react-native 中使用 react-navigation 包的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆