如何在webview中返回?我正在react-native中使用react-navigation包

ybzsozfc  于 2022-11-25  发布在  React
关注(0)|答案(3)|浏览(265)

我在react-native中安装了react-navigation软件包
我已经实现了标签导航,其中一个是在webview格式实现的。
我的问题是,如果我在Android上按下后退物理按钮,我会从应用程序本身转到上一个标签页,而不是从WebView返回。
我已经在互联网上为webview应用了后退按钮,但我还没有这样做。
我尝试在调试时显示onNavigationStateChange日志,但在第一次启动时加载url后,当url被移动时,它没有更新。下面是我实现的代码:

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;
ejk8hzay

ejk8hzay1#

按照官方的webview文档,你可以尝试这样做:https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes
通常情况下,您几乎可以做到这一点,但是YT导航的工作方式使得无法通过 onNavigationStateChange 捕获它,这就是为什么我们注入一个JS代码,该代码可以拦截这些哈希更改并向父组件发布一条消息,然后我们在 onMessage 处理程序中捕获它并正确设置状态变量。属性添加到您的示例中应该可以解决您的问题。
我为您准备了一个组件,它似乎可以满足您的需求:

* 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;
zf9nrax1

zf9nrax12#

上面的响应是完美的。不过我将canGoBack的状态设置为true;我得到一个空错误,所以:

constructor(props) {
    super(props);
    this.startingUrl = "https://app.vethorcardpag.com.br/GIF/login/0/";
    this.state = {
        canGoBack : true
    }
    this.handleBackButton = this.handleBackButton.bind(this);
}
2guxujil

2guxujil3#

下面是一个使用React's State的魔力的简单解决方案。
希望这对你有帮助。

import React, { useRef, useState } from 'react'

export default function Component () {

    // This is used to save the reference of your webview, so you can control it
    const webViewRef = useRef(null);

    // This state saves whether your WebView can go back
    const [webViewcanGoBack, setWebViewcanGoBack] = useState(false);

    const goBack = () => {

        // Getting the webview reference
        const webView = webViewRef.current
        
        if (webViewcanGoBack)
            // Do stuff here if your webview can go back 
        else
            // Do stuff here if your webview can't go back 
    }

    return (        
        <WebView
            source={{ uri: `Your URL` }}
            ref={webViewRef}
            javaScriptEnabled={true}
            onLoadProgress={({ nativeEvent }) => {
                // This function is called everytime your web view loads a page
                // and here we change the state of can go back
                setWebViewcanGoBack(nativeEvent.canGoBack)
            }}
        />
    )
}

原始答案https://stackoverflow.com/a/74500469/7823800

相关问题