React-router6的版本使用总结

428 阅读2分钟

1.1基础使用

安装版本 "react-router-dom": "^6.3.0",

import logo from "./logo.svg";
import "./App.css";
import { BrowserRouter, Routes, Route,Link } from "react-router-dom";
const Home = () => "home";
const About = () => "这是about";

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <BrowserRouter>
          <Routes>
            <Route index element={<Home />} />
            <Route path="/about" element={<About />} />
          </Routes>
          <Link to="/about">About</Link>
          <Link to="/">home</Link>
        </BrowserRouter>
      </header>
    </div>
  );
}

export default App;
  • BrowserRouter:浏览器环境下使用,不添加会报错。
  • Routes:路由的包裹
  • Route:实际的路由
  • Link: 跳转路由的边界线按钮 注:BrowserRouter/Routes等,只是路由规则,在界面上是看不到的,可以通过修改浏览器的地址栏看到切换效果; 想要在页面上操作路由切换用Link;

1.2 动态路由

useParams:可以拿到动态参数 path='*' 兜底的路由

  <Route path='/child' >
    <Route path=":invoiceId" element={<Home />} />
    <Route path="sent" element={< >舒适的房间</>} />
  </Route>
  <Route path="*" element={< >嘟嘟嘟嘟</>} />
  </Routes>

 <Link to='/child/dddd'>
  invoiceId
  </Link>
  <Link to='/child/send'>
  send
  </Link>
          
  const Home = () =>  {
  let params = useParams();
  console.log('params',params)
  return "home"};

1.3 深层路由

```js
<Routes>
  <Route path="/users/*" element={<Users />} />
</Routes>;

// and now deeper in the tree
function Users() {
  return (
    <div>
      <h1>Users</h1>
      <Routes>
        <Route path="account" element={<Account />} />
      </Routes>
    </div>
  );
}
```js

1.4 配合懒加载使用

 const About = React.lazy(() => import("./pages/About"));
 
<Route
    path="about"
    element={
      <React.Suspense fallback={<>...</>}>
        <About />
      </React.Suspense>
    }
/>

1.5 方法跳转

 const Home = () =>  {
  let params = useParams();
  const mavigate = useNavigate();
  console.log('params',params)
  return <div>''home
    <button onClick={() => {
      mavigate('/about')
    }}>跳转到about</button>
  </div> 

};

2.1 withRouter 为什么没了

withRouter 是将history, location, match就会被放进这个组件的props,往下传递。 v6的版本更希望通过hook实现这些功能(useParams,useLocation等)

2.2 V6中只支持 <Route element>

参考React 中Suspense的用法,<Suspense fallback={<Spinner />}>,传入的是React 元素,而非组件,可以将props更容易的传入到对应的元素内(社区推荐) 1. 可以隐式的传递props到元素内 1. V6以下形式的包版本体积过大

2.3为什么取消正则路由

  1. 正则路由为V6版本的路由排序带来很多问题,比如,如果定义一个正则的优先级?
  2. 正则路由占据了React Router近1/3的体积
  3. v6通过枚举解决正则的问题

3.实现一个React-router

import logo from "./logo.svg";
import "./App.css";
import { useEffect, useState,createContext } from "react";

const RouterContext = createContext(); // path改变
const HistoryContext = createContext(); // 子组件可以订阅方法

const BrowserRoute =(props) => {
  const [path,setPath] = useState(window.location.pathname || '/'); //首次渲染
   useEffect(() => {
     window.addEventListener('popstate',handleFun)

     return () => {
       window.removeEventListener('popstate',handleFun)
     }
   },[])
   const handleFun =() => {
     let {pathname} = window.location;
     console.log('-----')
     setPath(pathname);
   }
   const push =(path) => {
      setPath(path); // path 发生改变让界面发生变化
      window.history.replaceState({path},null,path); // 并不会变化
   }
   const go =() => {
     window.history.go(-1);
   }
   return (
     <RouterContext.Provider value={path}>
       <HistoryContext.Provider value={{push,go}}> //子组件订阅方法
         {props.children}
       </HistoryContext.Provider>
     </RouterContext.Provider>
   )
}

const Route =(props) => {
  const {component,path:pathName} = props;
  return (<RouterContext.Consumer> //订阅path
    {(path) => {
      console.log('----',path)
      return pathName === path?component:null;
    }}
  </RouterContext.Consumer>)
}


function App() {

  return (
    <div className="App">
      <header className="App-header">
      <BrowserRoute>
        <Route path='/' component={<div>saf</div>}></Route>
        <Route path='/about' component={<div>about</div>}></Route>
        <Route path='/home' component={<div>home</div>}></Route>
      </BrowserRoute>
       
      </header>
    </div>
  );
}

export default App;

问题:history.pushState 不会引起界面变化,此类事件只在点击前进后退按钮才生效, 因此,React Router使用history对象来监听事件的变化(pop,push)

  let history = createBrowserHistory();
    history.listen(({ location, action }) => {
      // this is called whenever new locations come in
      // the action is POP, PUSH, or REPLACE
    });