React路由 v6 VS v5

564 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

组件方面

React-Router6版本移除了<Switch/>组件,并使用<Routes/>替换。v5中Switch可以根据当前的路由 path ,匹配唯一的 Route 组件加以渲染。但是 Switch 本身是可以被不用的,v6则必须使用Routes

React-Router6移除了<Redirect/>组件,但可以使用新增的<Navigate/>组件配合<Route/>组件实现重定向效果。注:Navigate可接收绝对路径和相对路径

属性方面

React-Router6版本移除了componentrender属性,使用element属性替代

代码演示

React-Router5 设置路由组件

<Switch> 
    <Route path="/home" component={Home} /> 
    <Route path="/login" render={()=><Login/>}/>
</Switch>

React-Router6 设置路由组件

<Routes> 
    <Route path="/home" element={<Home/>} /> 
    <Route path="/login" element={<Login/>} /> 
</Routes>

React-Router5 设置重定向

<Route path='/user'}> 
    <Redirect to="/user/info" />
    {/* <Redirect to="info" /> */} 
</Route>

React-Router6 设置重定向

<Route path="/user" element={<Navigate to="/user/info"/>}> 
<Route path="/user" element={<Navigate to="../info"/>}>

props方面

React-Router5路由组件props会自动添加history、location、match三个路由相关属性用来操作路由,其中history用来进行路由跳转,location用来进行参数获取,match用来获取params参数。

注意:并且不是路由组件想要使用路由属性也是可以的,可以使用withRouter高阶组件包裹和和相应的hooks如useHistoryuseRouteMatchuseParams来实现。 其中

  • `useHistory`获取 `history` 对象
    
  • `useRouteMatch`获取当前路由的匹配信息
    
  • `useParams`获取 url 上的动态路由信息
    

但是在React-Router6中,路由组件props不再自动注入history、location、match三个路由相关属性。并且移除了withRouter高阶组件

代码演示-实现路由跳转

React-Router5


 1.声明式导航 
 
     (1)字符串形式 
     
    <Link to="/home" /> 
    
     (2)对象形式 
     
    <Link to={{ pathname: "/home" }} /> 
    
 2.编程式导航 
 
     (1)函数组件
     
         //使用props 
         
            props.history.push("/home") 
            
            props.history.replace("/home") 
            
         //使用hooks
         
            const history = useHistory("/home") 
            
            history.push("/home") 
            
            history.replace("/home") 
            
     (2)类组件 
     
        this.props.history.push("/home") 
        
        this.props.history.replace("/home")

React-Router6

封装withRouter高阶组件

作用:使类组件可以使用路由

import { useLocation, useNavigate, useParams } from "react-router";
// https://github.com/remix-run/react-router/issues/7256 
export default function withRouter(Child) { 

return (props) => {

const location = useLocation(); 
const navigate = useNavigate();
const params = useParams() 

return (
<Child {...props} navigate={navigate} location={location} params={params} /> 
) } }

路由跳转

 1.声明式导航 
 
     (1)字符串形式 
     <Link to="/home">home</Link>

     (2)对象形式 
     <Link to={{ pathname: "/home"}}>home</Link>
     
 2.编程式导航 
 
     (1)函数组件
      // 函数组件通过props.navigate或useNavigate实现跳转。
      
     (2)类组件 
      // 类组件通过高阶组件withRouter中的this.props.navigate实现跳转。 
      
     (3)实现跳转
     // navigate 相对路径形式 
     navigate("../home1/home11");
     
     // navigate 绝对路径形式 
     navigate("/home/home1/home11");
     
     // navigate 对象形式    
     navigate({ pathname: "/home/home1/home11"});

参数方面

React-router5

传参

支持params、search、state三种参数。

 1.声明式导航 
 
     (1)字符串形式 
         <Link to="/home?sort=name" />

     (2)对象形式 
         <Link to={{ 
             pathname: "/home",
             search: "?sort=name", 
             hash: "#the-hash", 
             state: { flag: true } 
         }} />
     
 2.编程式导航 
 
     (1)函数组件
          // 函数组件通过props.navigate或useNavigate实现跳转。
          字符串形式
              props.history.push("/home?sort=name")
          对象形式
              props.history.push({
                  pathname: "/home", 
                  search: "?sort=name", 
                  hash: "#the-hash",
                  state: { flag: true } 
              })      
     (2)类组件 
          // 类组件通过高阶组件withRouter中的this.props.navigate实现跳转。 
          字符串形式
              this.props.history.push("/courses?sort=name")
          对象形式
              this.props.history.push({
                  pathname: "/courses", 
                  search: "?sort=name", 
                  hash: "#the-hash",
                  state: { flag: true } 
              })

获取

params需要我们配置动态路由,然后在路由的match.params或者在函数组件中使用useParams获取。

search使用前需要使用URLSearchParams封装。

state传递参数需要注意的一点是当使用HashRouter的时候,页面刷新state参数会丢失。

1.类组件 
    获取search参数
        this.props.location.search 
    获取state参数
        this.props.location.state
    获取params
        this.props.match.params 
2.函数组件 
    使用props
        获取search参数
            props.location.search 
        获取state参数
            props.location.state  
        获取params 
            props.match.params  
    使用hooks 
        const location = useLocation() 
        获取search参数
            location.search 
        获取state参数
            location.state 
        获取params
            match.useParams()

React-router6

传参

在类组件中使用withRouter高阶组件获取navigate来进行路由的跳转和传参。

在函数组件我们使用useNavigate获取navigate来进行路由的跳转和传参。

1.声明式导航
    字符串形式
        <Link to="home?name=home1#hash1" state={{ num: 1 }}>home</Link> 
    对象 
        <Link to={{ 
        pathname: "home2",search: "?name=home2",hash: "#hash2",}}
        state={{ num: 1 }}>home2</Link>
2.编程式导航
    navigate 相对路径形式
        navigate("../home3", { state: { num: "hh" } }); 
    navigate 绝对路径形式
        navigate("/home/home3",
        { state:
        { num: "hh" },
        replace: true,//重定向
        });

获取

params需要我们配置动态路由,在类组价我们可以使用自己封装的withRouter高阶组件通过params获取。在函数组件中使用useParams获取。

search在类组价中使用withRouter高阶组件中的location获取。在函数组件可以使用useSearchParamsuseLocation获取。

state在类组价中使用withRouter高阶组件中的location获取。在函数组件可以使用useLocation获取。需要注意当使用HashRouter的时候,页面刷新state参数会丢失。

1.类组件
    (1)获取search参数
        this.props.location.search 
    (2)获取state参数
        this.props.location.state 
    (3)获取params
        this.props.params  
2.函数组件
    (1)使用props
         //获取search参数  
         props.location.search 
          // 获取state参数
          props.location.state props.params 
          // 获取params 
    (2)使用hooks 
          // 获取search参数 
          const location = useLocation() 
          const params = useParams() location.search 
           // 获取state参数
          location.state 
          // 获取params
          match.params 
          // 获取search参数 
          let [searchParams, setSearchParams] = useSearchParams()
          searchParams.get(xxx)

嵌套方面

React-router5

子路由配置需要写到对应的子页面,子路由需要补全父路由路径

// App.jsx 父组件 
    <Switch>
        <Route path="/home" component={<Home/>} />
        <Route path="/user" component={<User/>} /> 
    </Switch>
// User.jsx 子组件 
    <Switch>
        <Route path="/user/info" component={<UserInfo/>} /> 
        <Route path="/user/detail" component={<UserDetail/>} /> 
    </Switch>

React-router6

子路由可简写

App.jsx 父组件 
    <Routes> 
        <Route path="/home" element={<Home/>} /> 
        <Route path="/user/*" element={<User/>} /> 
    </Routes>
User.jsx 子组件
    <Routes>
        <Route path="info" element={<UserInfo/>} /> 
        <Route path="detail" element={<UserDetail/>} />
    </Routes>

实现类似vue的router-view效果

App.jsx 父组件
    <Routes> 
        <Route path="/home" element={<Home/>} /> 
        <Route path="/user" element={<User/>}>
            <Route path="info" element={<UserInfo/>} /> 
            <Route path="detail" element={<UserDetail/>} />
        </Route>
    </Routes> 
User.jsx 子组件 
    <Outlet />

通过配置渲染路由

React-Router5 使用 map 或 react-router-config通过配置渲染路由

定义routes

// routerConfig/routes.js

import Father from "./Father";
import Son1 from "./Son1";
import Son2 from "./Son2";

const routes = [
  {
    component: Fahter,
        exact: true,//精确查找   
    path: "/father",
    routes: [
      {
        path: "/Father/Son1",
        component: Son1,
      },
      {
        path: "/Father/Son2",
        component: Son2,
      },
    ],
  },
];

export default routes;

在根组件,我们需要自己使用map遍历渲染,并把子路由通过routes传递下去。

import routes from "./routerConfig/routes";

<BrowserRouter>
  <Switch>
    {routes.map((route) => {
      return (
        <Route
          path={route.path}
          key={route.path}
          render={(props) => {
            return (
              <route.component
                {...props}
                routes={route.routes}
              ></route.component>
            );
          }}
        ></Route>
      );
    })}
  </Switch>
</BrowserRouter>

在子组件我们还需要继续使用map遍历渲染。

// Parent.js

<Switch>
  {props.routes.map((route) => {
    return (
      <Route
        path={route.path}
        key={route.path}
        render={(props) => {
          return (
            <route.component
              {...props}
              routes={route.routes}
            ></route.component>
          );
        }}
      ></Route>
    );
  })}
</Switch>

使用react-router-config插件简化代码

下包yarn add react-router-config

在根组件使用renderRoutes方法

import { renderRoutes } 
from "react-router-config";
import routes from "./routerConfig/routes"; 
{renderRoutes(routes)}

在子组件使用renderRoutes

{renderRoutes(props.routes)}

React-Router6 使用useRoutes

首先定义routes

// routerConfig/routes.js

import Father from "./Father";
import Son1 from "./Son1";
import Son2 from "./Son2";

const routes = [
  {
    element: <Father></Father>,
    path: "/father",
    children: [
      {
        path: "Son1",
        element: <Son1></Son1>,
      },
      {
        path: "Son2",
        element: <Son2></Son2>,
      },
    ],
  },
];

根组件中

import { useRoutes } from "react-router-dom";
import routes from "./routerConfig/routes";

function App() {
 return {useRoutes(routes)}
}

子组件中,使用Outlet渲染

import { Outlet } from "react-router-dom";

<Outlet />

参考

基本使用苏苏同学

原理分析我不是外星人