yarn create vite
在项目当前目录下安装依靠插件:
1、yarn add axios
2、yarn add react
3、 yarn add react-redux
4、 yarn add react-router-dom
5、yarn add redux
6、yarn add reset-css
7、yarn add sass
8、yarn add vite-plugin-svg-icons
9、yarn add postcss-pxtorem
10、目录
api/user/index.ts
import { get } from "@/api/http";
export const user = {
getUserInfo: () => get("/user"),
};
api/http.ts
import http from "@/http";
export interface ApiResult {
code: number;
message: string;
data: any | null | object;
}
export async function get(url: string, params?: any): Promise<ApiResult> {
const response = await http.get<ApiResult>(url, { params });
return response?.data;
}
export async function post(url: string, data?: any): Promise<any> {
const response = await http.post<ApiResult>(url, data);
return response?.data;
}
export async function put(url: string, data?: any): Promise<any> {
const response = await http.put<ApiResult>(url, data);
return response?.data;
}
export async function del(url: string, params?: any): Promise<any> {
const response = await http.delete<ApiResult>(url, { params });
return response?.data;
}
api/index.ts
export * from "./user/index";
components/SvgIcon
import { useMemo } from "react";
interface propsInterface {
name: string;
size?: string;
color?: string;
profix?: string;
}
export default function SvgIcon(props: propsInterface) {
const size = props.size ?? "24px";
const color = props.color ?? "";
const profix = props.profix ?? "icon";
console.log(color);
const iconName = useMemo<string>(() => {
return `#${profix}-${props.name}`;
}, [profix, props.name]);
return (
<svg
style={{
height: size,
width: size,
fill: color,
position: "relative",
}}
aria-hidden="true"
>
<use xlinkHref={iconName} />
</svg>
);
}
http/index.ts
import axios from "axios";
const http = axios.create({
baseURL: "",
timeout: 5000,
});
// 添加请求拦截器
http.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加相应拦截器
http.interceptors.response.use(
function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对相应数据做点什么
return response;
},
function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对相应错误做点什么
return Promise.reject(error);
}
);
export default http;
Layout/Footer.tsx PC端圣杯结构上中下
Layout/Header.tsx
import { useNavigate } from "react-router-dom";
const Header = () => {
const navigate = useNavigate();
return (
<div className="wwj-flex">
<div className="wwj-cursor-pointer wwj-underline" onClick={() => navigate('/home')}>首页</div>
<div className="wwj-cursor-pointer wwj-underline wwj-ml-5" onClick={() => navigate('/pageone')}> age1</div>
</div>
)
};
export default Header;
Layout/index.tsx
import Header from "./Header"
import Footer from "./Footer"
import Style from './index.module.scss'
import { Outlet } from "react-router-dom"
const Layout = () => (
<div className={Style.root}>
<div className="header wwj-w-full wwj-h-[100px] wwj-bg-pink-300">
<Header />
</div>
<div className="main wwj-h-[900px]">
<Outlet />
</div>
<div className="footer wwj-h-[100px] wwj-bg-pink-300">
<Footer />
</div>
</div>
)
export default Layout
Layout/index.module.scss
.root {
:global {
width: 100%;
height: 100vh;
display: grid;
grid-template-rows: auto 1fr auto;
.header {
position: sticky;
top: 0;
}
}
}
pages/Home/index.tsx
import ViewOne from '@/pages/ViewOne/index'
import SvgIcon from '@/components/SvgIcon/index'
import { useEffect } from 'react';
import { user } from '@/api/index'
const Home = () => {
useEffect(() => {
getUserInfo()
}, [])
const getUserInfo = () => {
user.getUserInfo().then(res => {
console.log(res)
})
}
return (
<div>
首页
<ViewOne />
<SvgIcon name='age-icon' size='50' color='#c04a4a' />
<SvgIcon name='react' size='50' color='#c04a4a' />
</div>
);
};
export default Home;
pages/PageOne/index.tsx
const PageOne = () => (
<div> ageOne</div>
)
export default PageOne
pages/ViewOne/index.tsx
const ViewOne = () => (
<div>
ViewOne
</div>
)
export default ViewOne
router/index.tsx
import { lazy } from 'react';
import { useRoutes, RouteObject } from "react-router-dom"
import lazyLoad from './Lazy';
const routes: RouteObject[] = [
{
path: '/',
element: lazyLoad(lazy(() => import('@/Layout/index'))),
children: [
{
path: '/home',
element: lazyLoad(lazy(() => import('@/pages/Home/index')))
},
{
path: '/pageone',
element: lazyLoad(lazy(() => import('@/pages/PageOne/index')))
}
]
}
]
const BaseRouter = () => useRoutes(routes)
export default BaseRouter
router/Layzy.tsx
import { Suspense } from "react";
const lazyLoad = (Com: React.LazyExoticComponent<any>) => {
return (
<Suspense>
<Com />
</Suspense>
);
};
export default lazyLoad;
styles/gobal.scss
$color: white;
body {
// 禁止选中文字
user-select: none;
background-color: $color;
}
img {
// 禁止拖动图片
-webkit-user-drag: none;
}
styles/tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities;
utils/pxToRem.ts
// 基准巨细
const baseSize = 16;
// 设置 rem 函数
function setRem() {
// 当前页面宽度相对于 750 宽的缩放比例,可根据本身需要修改。
const scale = document.documentElement.clientWidth / 375;
// 设置页面根节点字体巨细
document.documentElement.style.fontSize =
baseSize * Math.min(scale, 2) + "px";
}
// 初始化
setRem();
// 改变窗口巨细时重新设置 rem
window.onresize = function () {
setRem();
};
App.tsx
import BaseRouter from "./router";
function App() {
return (
<BaseRouter />
)
}
export default App
main.tsx
import ReactDOM from 'react-dom/client'
import App from './App1.tsx'
import 'reset-css'
import '@/styles/global.scss'
import '@/styles/tailwind.css'
import '@/utils/pxToRem.ts'
import 'virtual:svg-icons-register'
import { BrowserRouter } from 'react-router-dom'
ReactDOM.createRoot(document.getElementById('root')!).render(
<BrowserRouter>
<App />
</BrowserRouter>
)
tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
screens: {
sm: '480px',
md: '768px',
lg: '976px',
xl: '1440px',
},
spacing: {
'1': '4px',
'2': '8px',
'3': '12px',
'4': '16px',
'5': '20px',
'6': '24px',
}
}
},
plugins: [],
prefix: 'wwj-',
}
tsconfig.json
{
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src"]
}
tsconfig.node.json
{
"compilerOptions": {
"composite": true,
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"strict": true,
"noEmit": true
},
"include": ["vite.config.ts"]
}
vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import legacy from "@vitejs/plugin-legacy";
import { resolve } from "path";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
import postCssPxToRem from "postcss-pxtorem";
import tailwindcss from "tailwindcss";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
legacy({
targets: ["defaults", "not IE 11"],
}),
createSvgIconsPlugin({
// 指定要缓存的图标文件夹
iconDirs: [
resolve(process.cwd(), "src/assets/svg"),
resolve(process.cwd(), "src/assets/icon"),
],
// 执行icon name的格式
symbolId: "icon-[name]",
}),
],
css: {
postcss: {
plugins: [
tailwindcss(),
postCssPxToRem({
// 换算基数,
rootValue: 16,
propList: ["*"],
}),
],
},
},
server: {
port: 9999,
open: true,
hmr: true,
proxy: {
"/user": {
target: "http://localhost:3999/user",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/user/, ""),
},
},
},
resolve: {
// 设置resole
alias: {
"@": resolve(__dirname, "./src"),
},
},
});
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |