6.1.4.react route

231 阅读1分钟

1. react-router 与react-router-dom

  • react-router React Router 核心
  • react-router-dom 用于 DOM 绑定的 React Router
  • react-router-native 用于 React Native 的 React Router

2. 页面跳转传参数

  • 方法一:url params - 形如/myurl/:id
this.props.history.push(`/myurl/${id}`);
const { id } = this.props.match.params
  • 方法二:query params - 形如 /myurl?id=1
const { search } = this.props.location;

const prevParams = qs.parse(search.replace(/^\?/, ''));

const params = { id: 1, name: 'chris' };
this.props.history.push({ pathname: '/myurl', 
        search: qs.stringify({ ...prevParams, ...params })});   
  • 方法三:url with state
this.props.history.push({ pathname: '/myurl', state: { num: 1 }});

const { state = {} } = this.props.location;

3. react-router-dom 相关hooks

import React from 'react';
import { useParams, useLocation, useHistory } from 'react-router-dom';
import qs from 'qs';

function MyUrl () {
    // 跳转url
    const history = useHistory(); // hook: useHistory

    function changeUrl () {
        history.push({
            pathname: '/myurl/2',
            search: 'name=chris',
            state: { fromSource: 1 },
        })
    }

    // 获取match params
    const params = useParams(); // hook: useParams
    const { id } = params;

    // 获取location params
    const location = useLocation(); // hook: useLocation
    const { search, state = {} } = location;
    // 获取location.search中的参数
    const { name } = qs.parse(search.replace(/^\?/, ''));
    // 获取location.state中的参数
    const { fromSource } = state;

    return (
        <div>
            <div>
                myurl id: { id },<br/>
                search name: { name },<br />
                state fromSource: { fromSource },<br />
            </div>
            <div onClick={ changeUrl }>
                change url
            </div>
        </div>
    )
}


export default MyUrl;

// 路由
const route = {
    path: '/myurl/:id',
    component: myUrl,
};
<Route path={route.path} component={route.component} />

3原理

BrowserRouter

import {createContext} from 'react';

const HistoryContext = createContext();

function BrowserRouter(props) {
  const [path, setPath] = useState(() => {
    // 首次渲染,获取到对应的路由
    const {pathname} = window.location;
    return pathname || '/';
  });

  ...

  // 点击ui跳转页面
  const push = function(path) {
    setPath(path);
    window.history.pushState({path}, null, path);
  }

  const goBack = function() {
    window.history.go(-1);
  }

  return (
    <RouterContext.Provider value={path}>
      <HistoryContext.Provider value={{
        push,
        goBack
      }}>
        {props.children}
      </HistoryContext.Provider>
    </RouterContext.Provider>
  );
}

HashRouter


import {useEffect, useState} from 'react';
import RouterContext from './routerContext';
import HistoryContext from './historyContext';

// 自定义HashRouter
function HashRouter(props) {
  const [path, setPath] = useState(() => {
    const {hash} = window.location;
    if(hash) {
      return hash.slice(1);
    }
    return '/#/';
  });

  useEffect(function componentDidMount() {
    // 监听用户点击浏览器的前进,后退按钮跳转页面
    window.addEventListener('hashchange', handlePopstate);
    
    return function componentWillUnmount() {
      window.removeEventListener('hashchange', handlePopstate);
    }
  }, []);

  const handlePopstate = function(event) {
    const {hash} = window.location;
    setPath(hash.slice(1));
  }

  //history Api: https://developer.mozilla.org/zh-CN/docs/Web/API/History_API

  // 点击ui跳转页面
  const push = function(path) {
    window.location.hash = path;
  }

  const goBack = function() {
    window.history.go(-1);
  }

  return (
    <RouterContext.Provider value={path}>
      <HistoryContext.Provider value={{
        push,
        goBack
      }}>
        {props.children}
      </HistoryContext.Provider>
    </RouterContext.Provider>
  );
}

export default HashRouter;

参考文章:

react-router几种带参数跳转

从0到1实现react-router

欢迎关注我的前端自检清单,我和你一起成长