最新消息:20210917 已从crifan.com换到crifan.org

【已解决】Preact-Router中如何通过路由实现返回上一页

ReactJS crifan 4169浏览 0评论

折腾:

【已解决】ReactJS导航栏显示返回按钮和标题以及右边图标

期间,需要实现:

对于不同的路由进来后,除了更新顶部Header中的图标,包括左边的返回按钮,同时要给返回按钮添加点击事件,或者是Link,以便于实现返回上一页

react router back link

preact router back link

javascript – react-router go back a page how do you configure history? – Stack Overflow

reactjs – Programmatically navigate using react router – Stack Overflow

javascript – Display Back button to go back like the browser back button when not in home path – Stack Overflow

preact-router back

用:

  goBackPage(){
    console.log(`this.context.router=${this.context.router}`);
    this.context.router.goBack();
  }
          <a onClick={this.goBackPage}>
            <span/>
          </a>

结果出错:

index.js?5c2a:415 Uncaught TypeError: Cannot read property ‘router’ of undefined
    at Object.goBackPage [as click] (eval at 349 (0.bd5b650….hot-update.js:7), <anonymous>:453:54)
    at HTMLAnchorElement.eventProxy (eval at <anonymous> (bundle.js:771), <anonymous>:96:32)

preact-router browserhistory back

[PReact] Handle Simple Routing with preact-router-IT大道

  goBackPage(){
    // console.log(`this.context=${this.context}`);
    console.log(`browserHistory=${browserHistory}`);
    console.log(`router=${router}`);
    console.log(`route=${route}`);
    console.log(`hashHistory=${hashHistory}`);
    console.log(`hashHistory._preactRouter=${hashHistory._preactRouter}`);
    console.log(`this._preactRouter=${this._preactRouter}`);
    // this.context.router.goBack();
    // browserHistory.goBack();
    // route(-1);
    hashHistory.goBack();
  }

都不行。

react router current route

preact router current route

暂时放一放,因为目前github无法打开,很多帖子和preact-router源码没法看。

等github能访问了,再弄。

然后目前用代码:

app.js

@connect(reducer, bindActions(actions))
export default class App extends Component {
  state = {
    curUrl : "/",
    prevUrl : "/"
  };
  constructor(props) {
    super(props);
    autoBind(this);
  }
  handleRoute = e => {
    console.log(e);
    // console.log(e.router.activeClassName);
    console.log(e.router);
    // console.log(e.router.title);
    const currentUrl = e.url;
    // const currentUrl = "/uapp" + e.url;
    // console.log(this.currentUrl);
    console.log(currentUrl);
    const previousUrl = e.previous;
    console.log(previousUrl);
    this.setState({
      curUrl : currentUrl,
      prevUrl : previousUrl
    });
    console.log(this.state.curUrl);
    window.scrollTo(0, 0);
  };
  render() {
    const prop = this.props;
    return (
      <div id="app">
        <Loading show={prop.globalLoadingShown}/>
        {/*<Header title={this.state.currentTitle}/>*/}
        <Header curUrl={this.state.curUrl} prevUrl={this.state.prevUrl}/>

header/index.js

export default class Header extends Component {
  state = {
    curUrl : "",
    prevUrl : "1"
  }
  constructor(props) {
    super(props);
    // this.state.curUrl = this.props.curUrl;
    // this.state.prevUrl = this.props.prevUrl;
    console.log(`Header constructor: this.state.curUrl=${this.state.curUrl}, this.state.prevUrl=${this.state.prevUrl}, this.props.curUrl=${this.props.curUrl}, this.props.prevUrl=${this.props.prevUrl}`);
  }
  componentWillReceiveProps(nextProps) {
    this.setState({
      curUrl: nextProps.curUrl,
      prevUrl: nextProps.prevUrl
    });
    // this.forceUpdate();
  }
  render() {
    const pageType = this.parsePageType(this.state.curUrl);
    console.log(`Header render: this.state.curUrl=${this.state.curUrl}, this.state.prevUrl=${this.state.prevUrl}, this.props.curUrl=${this.props.curUrl}, this.props.prevUrl=${this.props.prevUrl}`);
    return (
      <header class={style.header_div}>
        <div class={style.header_con}>
          { this.showLeftIcon(pageType, this.state.prevUrl) }
          <div class={style.top_tit}>{pageType.title}</div>
          { this.showRightIcon(pageType) }
        </div>
      </header>
    );
  }
  showLeftIcon(curPageType, prevUrl){
    console.log(`showLeftIcon: prevUrl=${prevUrl}`);
    if (curPageType.left.icon === HEADER_ICON.NONE) {
      return null;
    } else if (curPageType.left.icon === HEADER_ICON.BACK) {
      return (
          <Link href={prevUrl}>
            <span/>
          </Link>
      );
    } else if (curPageType.left.icon === HEADER_ICON.SWITCH_COW_FARM) {
      return (
          <Link href={curPageType.left.link} class={style.home_qc} >
            切换牛场
          </Link>
      );
    }
    return null;
  }

虽然实现了基本的,通过prevUrl,实现返回上一页,但是会出现嵌套死循环:

点击子页面,比如 处理 或者右上角的加号,进入子页面的子页面

但是此时点击返回,可以返回上一页:

但是再点击 返回,还是回到之前的子页面了(而非期望的主页面)

所以,还是没有真正解决问题。

-》

如果给每个页面,都强制指定一个前一页,则显得很麻烦。

-》希望还是可以通过history back类似的逻辑,即页面调用stack栈,智能的实现页面跳转。

所以还是:

等github可以访问后,再去研究

preact-router是否有history  back之类的功能

preact-router history back

Full hash-routing using preact-router · Issue #153 · developit/preact-router

Route Transitions · Issue #29 · developit/preact-router

preact-router history

javascript – How to use React Router with Preact – Stack Overflow

preact-router go back

reactjs – Using goBack function from react-router-redux – Stack Overflow

然后用了back的代码,结果点击返回按钮时出错:

【间接解决】Preact-Router调用传递过去的history的back时出错:Uncaught TypeError Illegal invocation

【总结】

Preact-router是支持history.back()去返回上一页的,但是只能在父页面中使用,即只能在Router所在的页面使用。

此处不能直接把history作为参数(比如叫routerHistory)传递给子页面,否则子页面中直接调用routerHistory.back是行不通的,会出错:Uncaught TypeError: Illegal invocation

解决办法是:

利用子页面调用父页面的函数,即可间接实现此效果:

把父页面的history.back()单独弄成函数,传递给子页面,然后子页面即可随时调用此函数,实现返回前一页了。

具体代码是:

父页面app.js

import { Router } from ‘preact-router’;
import { browserHistory } from ‘preact-router’;
import Header from ‘../components/header’;
@connect(reducer, bindActions(actions))
export default class App extends Component {
  state = {
    curUrl : "/",
    prevUrl : "/",
    routerHistory : null
  };
  constructor(props) {
    super(props);
    autoBind(this);
  }
  handleRoute = e => {
    console.log("handleRoute:");
    console.log(e);
    // console.log(e.router.activeClassName);
    console.log(e.router);
    // console.log(e.router.title);
    const currentUrl = e.url;
    // const currentUrl = "/uapp" + e.url;
    // console.log(this.currentUrl);
    console.log(currentUrl);
    // console.log(browserHistory);
    console.log(`history.location=${history.location}`);
    console.log("now do history.back()");
    // history.back();
    // console.log(`this.props.history=${this.props.history}`);
    // console.log(`this.state.history=${this.state.history}`);
    const previousUrl = e.previous;
    console.log(previousUrl);
    this.setState({
      curUrl : currentUrl,
      prevUrl : previousUrl,
      routerHistory : history
    });
    console.log(this.state.curUrl);
    window.scrollTo(0, 0);
  };
  goBackFunc(){
    console.log(`goBackFunc: history=${history}`);
    console.log(history);
    console.log(history.back);
    console.log("+++++ now do history.back()");
    history.back();
  }
  render() {
    const prop = this.props;
    return (
      …
       <Header curUrl={this.state.curUrl} prevUrl={this.state.prevUrl} routerHistory={this.state.routerHistory} goBackFunc={this.goBackFunc}/>
        <div class="container">
          <Router onChange={this.handleRoute} history={browserHistory}>
          {/*<Router onChange={this.handleRoute}>*/}
            <Main path="/" />
            <Profile path="/profile" />

子页面Header/index.js

export default class Header extends Component {
  state = {
    curUrl : "",
    prevUrl : "1",
    routerHistory : null
  }
  constructor(props) {
    super(props);
    // this.state.curUrl = this.props.curUrl;
    // this.state.prevUrl = this.props.prevUrl;
    console.log(`Header constructor: this.state.curUrl=${this.state.curUrl}, this.state.prevUrl=${this.state.prevUrl}, this.props.curUrl=${this.props.curUrl}, this.props.prevUrl=${this.props.prevUrl}`);
  }
  componentWillReceiveProps(nextProps) {
    this.setState({
      curUrl: nextProps.curUrl,
      prevUrl: nextProps.prevUrl,
      routerHistory : nextProps.routerHistory
    });
    // this.forceUpdate();
    // console.log(`Header componentWillReceiveProps: this.state.routerHistory=${this.state.routerHistory}, history=${history}, route=${route}, getCurrentUrl=${getCurrentUrl}`);
    console.log(`Header componentWillReceiveProps: this.state.routerHistory=${this.state.routerHistory}`);
  }
  render() {
    const pageType = this.parsePageType(this.state.curUrl);
    console.log(`Header render: this.state.curUrl=${this.state.curUrl}, this.state.prevUrl=${this.state.prevUrl}, this.props.curUrl=${this.props.curUrl}, this.props.prevUrl=${this.props.prevUrl}`);
    return (
      <header class={style.header_div}>
        <div class={style.header_con}>
          { this.showLeftIcon(pageType, this.props.goBackFunc) }
          {/*<a onClick={this.state.routerHistory.back}>*/}
          {/*<a onClick={this.state.routerHistory !== null ? this.state.routerHistory.back : ()=>{}}>*/}
          {/*<a onClick={this.props.goBackFunc}>
            <span/>
          </a>*/}
          <div class={style.top_tit}>{pageType.title}</div>
          { this.showRightIcon(pageType) }
        </div>
      </header>
    );
  }
          // <a onClick={this.goBackPage}>
          // <a onClick={route(prevUrl)}>
          //   <span/>
          // </a>
          // <Link href={prevUrl}>
          //   <span/>
          // </Link>
  // showLeftIcon(curPageType, prevUrl){
  //   console.log(`showLeftIcon: prevUrl=${prevUrl}`);
  // showLeftIcon(curPageType, curState){
  showLeftIcon(curPageType, goBackFunc){
    console.log(`showLeftIcon: goBackFunc=${goBackFunc}`);
    // console.log(`showLeftIcon: curState=${curState}`);
    // console.log(`showLeftIcon: curState.routerHistory=${curState.routerHistory}`);
    // console.log(curState.routerHistory);
    // if (curState.routerHistory !== null) {
    //   console.log(curState.routerHistory.back);
    //   const backFunction = curState.routerHistory.back;
    //   console.log(backFunction);
    // }
    if (curPageType.left.icon === HEADER_ICON.NONE) {
      return null;
    } else if (curPageType.left.icon === HEADER_ICON.BACK) {
      return (
          // <a onClick={backFunction}>
          // <a onClick={curState.routerHistory.back}>
          <a onClick={goBackFunc}>
            <span/>
          </a>
      );
    } else if (curPageType.left.icon === HEADER_ICON.SWITCH_COW_FARM) {
      return (
          <Link href={curPageType.left.link} class={style.home_qc} >
            切换牛场
          </Link>
      );
    }
    return null;
  }

效果是:

(1)比如最开始在首页

(2)点击了进入配种子页面

(3)点击处理

(4)点击返回之前页面

(5)点击加号去新增

(6)再点击返回

(7)此时,重点来了:点击返回就不会出现页面在之前的 处理和新增页面死循环的情况了,就可以正常返回首页了:

转载请注明:在路上 » 【已解决】Preact-Router中如何通过路由实现返回上一页

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
99 queries in 0.183 seconds, using 23.44MB memory