从Vue转React必备了解React - Router

132 阅读2分钟

URL中的Hash 模式

  • URL的hash也就是锚点(#), 本质上是改变window.location的href属性;
  • 我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新;

HTML5中的History

  • replaceState:替换原来的路径;
  • popState:路径的回退;
  • go:向前或向后改变路径;
  • forward:向前改变路径;
  • back:向后改变路径;

react-router (react-router-dom)

  • Router中包含了对路径改变的监听,并且会将相应的路径传递给子组件;
  • BrowserRouter使用history模式;
  • HashRouter使用hash模式;
import { HashRouter,BrowserRouter } from "react-router-dom"
  <HashRouter>
        <App/>
    </HashRouter>
    
      <BrowserRouter>
        <App/>
    </BrowserRouter>

路由配置

  • 在Router5.x中用的都是Switch组件
    • Router5.x使用的是component属性
    • exact:精准匹配,只有精准匹配到完全一致的路径,才会渲染对应的组件;
  • 在Router6.x中用的都是Routers组件
    • path属性:用于设置匹配到的路径;
    • element属性:设置匹配到路径后,渲染的组件;
    • exact:已经不需要了
  <Route path='/login' element={<Login/>}/>

路由跳转

  • Link组件 :最终会渲染成a标签
  • NavLink:它是Link的高阶层次(多了className和style的 需要传入一个函数(isActive))
  • 不管哪种组件 都会在激活状态下 加上一个active的class类
  • Navigate:重定向。当这个组件出现时,就会执行跳转到对应的to路径中:
  <NavLink to="/about" style={({isActive}) => ({color:  isActive ? "red":      ""})}>关于</NavLink> 

  <NavLink to="/home" className={({isActive}) => isActive?"link-active":""}>首页</NavLink>
  
  <Link to="/home" replace={false}>首页</Link>
  
  <Route path='/' element={<Navigate to="/home"/>}/>
  <Route path='*' element={<NotFound/>}/>

路由的嵌套

  • 可以直接在Route的组件标签内 继续写Route组件
  <Route path='/home' element={<Home/>}>
    <Route path='/home' element={<Navigate to="/home/recommend"/>}/>
    <Route path='/home/recommend' element={<HomeRecommend/>}/>
    <Route path='/home/ranking' element={<HomeRanking/>}/>
    <Route path='/home/songmenu' element={<HomeSongMenu/>}/>
  </Route>
  • 可以通过useRouter 函数抽离路由配置(react-router-config)
    • 可以使用路由懒加载 来进行分包处理
    • const About = React.lazy(() => import("../pages/About"))
    • 需要在App组件引入时候嵌套Suspense组件
      <Suspense fallback={<h3>Loading...</h3>}>
          <App/>
      </Suspense>
      
App页面
{useRoutes(routes)}


const About = React.lazy(() => import("../pages/About"))
const Login = React.lazy(() => import("../pages/Login"))

const routes = [
  {
    path: "/",
    element: <Navigate to="/home"/>
  },
  {
    path: "/home",
    element: <Home/>,
    children: [
      {
        path: "/home",
        element: <Navigate to="/home/recommend"/>
      },
      {
        path: "/home/recommend",
        element: <HomeRecommend/>
      },
    ]
  },
  {
    path: "/about",
    element: <About/>
  },

  {
    path: "*",
    element: <NotFound/>
  }
]

export default routes

手动路由跳转

在Router6.x版本之后 所有API都迁移到了Hooks中 如果想在类组件中时候Hooks的话 需要通过高阶组件方式进行嵌套(返回一个由函数组件内部嵌套的类组件)

  • useLocation:获取路由字符串参数
  • useNavigate:路由导航跳转
  • useParams:获取动态路由参数
  • useSearchParams:获取路由上字符串参数 /user?name=why&age=18
import { useLocation, useNavigate, useParams, useSearchParams } from "react-router-dom"

// 高阶组件: 函数
function withRouter(WrapperComponent) {
  return function(props) {
    // 1.导航
    const navigate = useNavigate()

    // 2.动态路由的参数: /detail/:id
    const params = useParams()

    // 3.查询字符串的参数: /user?name=why&age=18
    const location = useLocation()
    const [searchParams] = useSearchParams()
    const query = Object.fromEntries(searchParams)

    const router = { navigate, params, location, query }

    return <WrapperComponent {...props} router={router}/>
  }
}

export default withRouter