react+vite+ts+antd 搭建项目基础框架
分类: React 901 0
前言
- 距离上一个vue重构react项目已经有几个月了,最近在用vite写一些vue3的相关东西,看到vite支持react-ts模板,正好来体验下。
一、创建项目
pnpm create vite vite-react-test(自定义项目名称) --template react-ts
cd vite-react-test
pnpm install
pnpm run dev
目录结构如下:
- 通过alias配置@别名,替代../../方式访问
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
open: true
},
resolve: { // 设置项目文件导入路径
alias: [
{ find: '@', replacement: path.resolve(__dirname, './src') }
]
}
})
// tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"baseUrl": ".", // 新增
"paths": { // 新增
"@/*":["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx"],
"references": [{ "path": "./tsconfig.node.json" }]
}
- 这里需要安装两个依赖
pnpm install @types/node path
二、引入react-router-dom
pnpm install react-router-dom
- 在src目录下创建route文件夹,配置路由文件
// src/route/route-config.ts
import { lazy } from 'react'
const Login = lazy(() => import('@/pages/login'))
const Home = lazy(() => import('@/pages/home'))
const NotFound = lazy(() => import('@/pages/404'))
const RouteDemo = lazy(() => import('@/pages/demo/route-demo'))
const ReduxDemo = lazy(() => import('@/pages/demo/redux-demo'))
const ContextDemo = lazy(() => import('@/pages/demo/context-demo/view'))
export default [
{
path: '/',
meta: {
title: '首页',
isLogin: true
},
component: Home
},
{
path: '/login',
meta: {
title: '登录'
},
component: Login
},
{
path: '/demo',
component: lazy(() => import('@/pages/demo')),
children: [
{
path: '',
redirect: '/demo/route-demo',
},
{
path: '/demo/route-demo/*',
meta: {
title: 'react-route',
isLogin: true
},
component: RouteDemo,
},
{
path: '/demo/redux-demo',
meta: {
title: 'react-redux',
isLogin: true
},
component: ReduxDemo
},
{
path: '/demo/context-demo',
meta: {
title: 'react-context',
isLogin: true
},
component: ContextDemo
}
]
},
{
path: '*',
meta: {
title: '404'
},
component: NotFound
}
]
// src/route/index.tsx
import { Suspense } from 'react' // Suspense的作用是「划分页面中需要并发渲染的部分」
import { Navigate, useRoutes } from 'react-router-dom'
import routes from './route-config'
// 拦截
const RouterBeforeEach = (props: { route: any, children: any }) => {
if (props?.route?.meta?.title) {
document.title = props.route.meta.title;
}
// const isLogin: boolean = !!Cookies.get('userInfo')
const isLogin: boolean = true
if (props?.route?.meta?.isLogin) {
if (!isLogin) {
return <Navigate to={'/login'} replace />
}
}
// const location = useLocation()
const location = { pathname: '' }
const routerKey = location.pathname
if (isLogin && ['/login'].includes(routerKey)) {
return <Navigate to={'/'} replace />
}
return (
<Suspense>
{props.children}
</Suspense>
)
}
// 渲染路由
const renderRoutes = (routes: any) => {
return routes.map((item: any) => {
const route: any = { meta: item.meta, path: item.path }
if (item.component) {
// element 要接收react.element类型 item.component 是对象 所以要转一下
// 看着里看着里
route.element = <RouterBeforeEach route={item}><item.component /></RouterBeforeEach>
}
if (item.children) {
route.children = renderRoutes(item.children)
}
if (item.redirect) {
route.element = <Navigate to={item.redirect} />
}
return route
})
}
export default function Router() {
// console.log(renderRoutes(routes));
// useRoutes API 把路由数组整合为 <Router> <Route path="xx" element="xxx"></Route>等 </Router>的路由组件 直接用于BrowserRouter中
return useRoutes(renderRoutes(routes))
}
- 在src/App.tsx文件中引入写好的路由
// src/App.tsx
import Router from '@/route/index'
import { BrowserRouter } from 'react-router-dom'
function App() {
return (
<div className="App">
<BrowserRouter>
<Router></Router>
</BrowserRouter>
</div>
)
}
export default App
三、引入react-redux、 @reduxjs/toolkit
pnpm install react-redux @reduxjs/toolkit
- 在src目录下创建store文件夹,配置redux文件
// src/store/index.ts
import {configureStore} from '@reduxjs/toolkit'
import counterSlice from './redux-toolkit/counterSlice'
export default configureStore({
reducer: {
counter: counterSlice
}
})
// src/store/redux-toolkit/counterSlice.ts
import { createSlice } from '@reduxjs/toolkit'
interface typeState {
count: number,
title: string
}
const initialState: typeState = {
count: 1,
title: 'redux-toolkit'
}
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment(state, { payload }) {
state.count = state.count + payload.step;
},
decrement(state, { payload }) {
console.log(payload)
state.count -= payload.step
}
}
})
export const { increment, decrement } = counterSlice.actions
export const asyncdecrement = (payload: any) => (dispatch: (arg0: { payload: any; type: string; }) => void) => {
setTimeout(() => {
dispatch(decrement(payload))
}, 2000)
}
export default counterSlice.reducer
- 在src/main.tsx文件中引入store
// src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { Provider } from 'react-redux'
import store from './store/index'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
)
- 使用方式如下:
// src\pages\demo\redux-demo\index.tsx
import { useSelector, useDispatch } from 'react-redux'
import { increment, asyncdecrement } from '@/store/redux-toolkit/counterSlice'
const ReduxDemo = () => {
const { count } = useSelector((state: any) => state.counter)
const dispatch: any = useDispatch()
return (
<>
redux-demo
<p>redux-toolkit demo 同步<button onClick={() => { dispatch(increment({ step: 2 })) }}>{count}</button></p>
<p>redux-toolkit demo 异步<button onClick={() => { dispatch(asyncdecrement({ step: 1 })) }}>{count}</button></p>
</>
)
}
export default ReduxDemo
四、引入antd及修改antd默认主题
pnpm install antd less less-loader
- 在main.tsx中引入antd默认样式
// src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import 'antd/dist/antd.less'; // 引入antd默认样式
import { Provider } from 'react-redux'
import store from './store/index'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
)
- 修改主题
// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
open: true
},
resolve: { // 设置项目文件导入路径
alias: [
{ find: '@', replacement: path.resolve(__dirname, './src') }
]
},
css: {
preprocessorOptions: {
less: {
modifyVars: { // 更改主题在这里
// 'primary-color': '#52c41a',
// 'link-color': '#1DA57A',
// 'border-radius-base': '2px'
},
javascriptEnabled: true
}
}
}
})
共 0 条评论关于 “react+vite+ts+antd 搭建项目基础框架”