react18+router6+Antd 项目搭建1

npm i -g create-react-app
// 初始化项目
npx create-react-app 项目名称
// 引入antdesign, sass, react-router-dom, axios等需要的依赖
yarn add ... 
// 默认指令启动项目
yarn start 
// 有些没用的目录可以删掉, 再自行添加一些其他的目录结构

大概目录结构

// index.js 入口

import React from 'react';
import ReactDOM from 'react-dom/client';
import 'antd/dist/antd.min.css'
// 后导入全局样式文件,防止样式覆盖
import './index.scss';
import App from './App';
// 性能指标相关的,可以先去掉
import reportWebVitals from './reportWebVitals';
// 内部实现是用了 history 这个库和 React Context 来实现的,所以当你的用户前进后退时,history 这个库会记住用户的历史记录,这样需要跳转时可以直接操作
import { BrowserRouter as Router } from 'react-router-dom'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Router>
    <App />
  </Router>
);

// 这样控制台可以打印出相关性能数据,小瞄一眼
reportWebVitals(console.log);
// App.js 

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

function App() {
  // 返回与当前位置匹配的路由元素,参数: 创建的路由对象
  return useRoutes(routers);
}

export default App;

// router/index.js 管理路由组件

import AppLayout from '../views/layout/index';
import Menu11 from '../views/menu1/menu1-1'
import Menu22 from '../views/menu1/menu2-2'
import Login from '../views/login'
import Home from '../views/home'

export const routers = [
  {
    path: '/',
    element: <AppLayout />,
    // 路由嵌套,子路由的元素需使用<Outlet />
    children: [
      {
        index: true,
        element: (<Home />)
      }, 
      {
        path: '/Menu11',
        element: (<Menu11 />)
      }, 
      {
        path: '/Menu22',
        element: (<Menu22 />)
      }
    ]
  },
  {
    path: '/login',
    element: (<Login />)
  }

]
// layout.js 组件

import { Breadcrumb, Layout, Menu } from "antd";
import { MailOutlined, RedditOutlined } from "@ant-design/icons";
import React, { useState } from "react";
import { Outlet, useNavigate, } from "react-router-dom";
// 根目录 @ 要配置
import "@/styles/index.scss";

const { Header, Content, Sider, Footer } = Layout;

function getItem(label, key, icon, children, type) {
  return {
    key,
    icon,
    children,
    label,
    type,
  };
}

const items1 = ["1", "2", "3"].map((key) => ({
  key,
  label: `nav ${key}`,
}));

// key值和router中定义相同
const items = [
  getItem("Menu One", "Menu1", <MailOutlined />, 
  	[getItem("Menu1", "/Menu11"), getItem("Menu2", "/Menu22")]
  ),
];

const rootSubmenuKeys = ["Menu1"];

const App = () => {
  const [openKeys, setOpenKeys] = useState(["Menu1"]);

  const onOpenChange = (keys) => {
    const latestOpenKey = keys.find((key) => openKeys.indexOf(key) === -1);

    if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
      setOpenKeys(keys);
    } else {
      setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
    }
  };

  const Navigate = useNavigate();

  const toPage = (e) => {
    Navigate(e.key);
  };

  return (
    <Layout style={{ height: "100%" }}>
      <Header className="header">
        <RedditOutlined style={{ fontSize: "66px" }} />
        <Menu
          theme="light"
          mode="horizontal"
          defaultSelectedKeys={["2"]}
          items={items1}
          style={{ flex: "1" }}
        />
      </Header>
      <Layout>
        <Sider width={200} className="site-layout-background">
          <Menu
            mode="inline"
            openKeys={openKeys}
            onOpenChange={onOpenChange}
            style={{ height: "100%", borderRight: 0 }}
            items={items}
            onClick={toPage}
          />
        </Sider>
        <Layout
          style={{
            padding: "0 24px",
          }}
        >
          <Breadcrumb
            style={{
              margin: "16px 0",
            }}
          >
            <Breadcrumb.Item>Home</Breadcrumb.Item>
            <Breadcrumb.Item>List</Breadcrumb.Item>
            <Breadcrumb.Item>App</Breadcrumb.Item>
          </Breadcrumb>
          <Content
            className="site-layout-background"
            style={{
              padding: 24,
              margin: 0,
              minHeight: 280,
            }}
          >
            {/* 这里注意!之前没有写<Outlet /> 在路由上浪费了好多时间 */}
            <Outlet />
          </Content>
        </Layout>
      </Layout>
      <Footer
        style={{
          textAlign: "center",
        }}
      >
        react_demo ©2022 Created by Arbor
      </Footer>
    </Layout>
  );
};

export default App;

运行界面

关于webpack配置问题

脚手架创建的react项目初始化是没有webpack.config.js等相关配置文件的,默认都是隐藏的
初始package.json文件,配置的命令都是 “react-scripts *” 来执行的

// 这个命令就是提供出来 生成一个config目录,相关的配置文件都在内
// yarn eject 是不可逆操作
"eject": "react-scripts eject",

第一步主要是想设置一个根路径,没有用 eject 重写配置可以使用 craco 来覆盖

// 安装craco相关依赖
yarn add @craco/craco craco-less @babel/plugin-proposal-decorators babel-plugin-import

// package.json 

"scripts": {
  "start": "set PORT=5000 && craco start",
  "build": "craco build",
  "test": "craco test"
},
// craco.config.js

const path = require("path")
// 定义函数resolve, 将自定义的路径和js的根路径拼接起来
const resolve = (dir) => path.resolve(__dirname, dir);

module.exports = {
    webpack:{
        alias:{
          "@": resolve("src")
        }
    },
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值