落笔 Blog

落笔
Be a hero of your own
  1. 首页
  2. 随笔系列
  3. 正文

从0-1用react+typescript的路由设置学习

2023年4月21日 1080点热度 0人点赞 0条评论

前言:22年12月份结束了实习,在等毕业证的这段时间里,自己也是就感兴趣的地方原理进行了一番学习,实操,之前很多的项目里,要么就是原来配置好的,照葫芦画瓢添加路由,要么就是脚手架集成的,自己想从0-1实现一下基本的路由配置,基于技术与时俱进的原则,这里就 react router v6 探索,后续与 react router v5 版本的差别再好好思考一番。

我的开发环境:mac+vscode+node(v16.20.1)
仓库地址:https://github.com/hyh-op/react-router

基本框架安装

  1. 脚手架构建一个react+ts 项目。
npx create-react-app react-router --template typescript
  1. 安装路由v6版本的依赖(安装失败的注意下node版本)
yarn add react-router-dom@6 react-router@6
//npm i react-router-dom@6 react-router@6
  1. 在index.tsx 中,必须用路由组件包裹APP。
import React from 'react';
import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
import './index.css';

const container = document.getElementById('root')!;
const root = createRoot(container);

root.render(
  <BrowserRouter>
    <React.StrictMode>
      <Provider store={store}>
        <App />
      </Provider>
    </React.StrictMode>
  </BrowserRouter>
);
reportWebVitals();
  1. 构建项目,页面结构如下:
    路由结构

然后根据页面结构,码出对应的页面
页面
二级路由的页面都如上图所示
两个一级路由的页面(MainLayout页和AccountLayout的页)需要有插槽匹配二级路由,Outlet 组件可以将与子路由相匹配的元素显示出来

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

const MainLayout: React.FC = (): JSX.Element => {
  return (
    <div>
      MainLayout
      <br />
      <Outlet />
    </div>
  );
};

export default MainLayout;
  1. 用React Router v6 提供的useRoutes hook 搭建路由。
    App.tsx页面
import './App.css';
import { useRoutes } from 'react-router';
import { accountRoutes, mainRoutes } from './router/routes';

function App() {
  const routing = useRoutes([mainRoutes, accountRoutes]);
  return (
    <>
      {routing}
    </>
  );
}

export default App;

routes.js路由匹配

import { Navigate } from 'react-router-dom';
import MainView from '../main/MainView';
import MainLayout from '../main/MainLayout'
import PageNotFoundView from '../errror/PageNotFoundView'
import AccountLayout from '../account/AccountLayout'
import AccountDetailView from '../account/AccountDetailView'
import AccountAddView from '../account/AccountAddView'
import AccountListView from '../account/AccountListView'

export const mainRoutes = {
    path: '/',
    element: <MainLayout />,
    children: [
        { path: '*', element: <Navigate to='/404' /> },
        { path: '/', element: <MainView /> },
        { path: '404', element: <PageNotFoundView /> },
        { path: 'account', element: <Navigate to='/account/list' /> },
    ]
}
export const accountRoutes = {
    path: 'account',
    element: <AccountLayout />,
    children: [
        { path: '*', element: <Navigate to='/404' /> },
        // :id 动态参数。
        { path: ':id', element: <AccountDetailView /> },
        { path: 'add', element: <AccountAddView /> },
        { path: 'list', element: <AccountListView /> },
    ]
}

路由匹配的效果如下
路由匹配效果图

  1. 在首页MainLayout 中建立导航栏,用Link 组件实现页面跳转。
    MainLayout.tsx页面
import React from "react";
import { Link, Outlet } from "react-router-dom";

const MainLayout: React.FC = (): JSX.Element => {
    return (
        <div>
            MainLayout
            <br />
            <Outlet />
            {/* outlet :嵌套路由,可以保证子路由共享父路由的界面而不会覆盖。
            为此React提供了Outlet组件,将其用于父组件中可以为子路由的元素占位,
            并最终渲染子路由的元素。 */}

            <>
                点击连接跳转的部份如下:
                {/* nav语义标签 */}
                <nav>
                    <ul>
                        <li><Link to='/'>Main Page</Link></li>
                        <li><Link to='/account/add'>Add Account</Link></li>
                        <li><Link to='/account/list'>List Accounts</Link></li>
                        <li><Link to='/account/1'>View Account</Link></li>
                        <li><Link to='/something-else'>Not Found</Link></li>
                    </ul>
                </nav>
                <Outlet />
            </>
        </div>
    );
};

export default MainLayout;

效果如图所示:
路由

若是想用js 跳转页面,要把以前的useHistory 换成useNavigate。

import React from "react";
import { Link, Outlet, useNavigate } from "react-router-dom";

const MainLayout: React.FC = (): JSX.Element => {
  let navigate = useNavigate();
  return (
    <div>
          ……
        <nav>
          ……
        <button
          onClick={() => {
            navigate("/account/add");
          }}
        >
          Add Account
        </button>
      </nav>
      <Outlet />
    </div>
  );
};

export default MainLayout;
  1. 使用useParams hook 可以获取路由传递的参数。
    AccountDetailView页面
import React from 'react';
import { useParams } from 'react-router-dom';

const AccountDetailView: React.FC = (): JSX.Element => {
    const params = useParams();
    return (
        <div>
            {`View Account ID "${params.id}"`}
        </div>
    );
};

export default AccountDetailView;

效果如图所示:
路由

参考文章

整体参考:https://juejin.cn/post/7088526716049555492

标签: 暂无
最后更新:2023年8月4日

落笔

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

© 2022 落笔 Blog.

One Piece is a real treasure

粤ICP备2023064929号