Umi4最佳实践(个人向)
Umi4最佳实践(个人向)
非Max版本
1.新建项目文件夹进入对应的文件夹
mkdir 文件夹名称 && cd 文件夹名称
//此处specification为例子
mkdir specification && cd specification
2.安装umi框架依赖
npx create-umi@latest
或
yarn create umi
//注:如果没有yarn 需要通过npm i yarn -g 全局安装
3.启用 Prettier(前端代码格式化工具)
pnpm umi g
✔ Pick generator type › Enable Prettier -- Enable Prettier
项目中会自动生成文件
4.了解和使用prettier的属性
/* prettier的配置 */
"prettier.printWidth": 100, // 超过最大值换行
"prettier.tabWidth": 4, // 缩进字节数
"prettier.useTabs": false, // 缩进不使用tab,使用空格
"prettier.semi": true, // 句尾添加分号
"prettier.singleQuote": true, // 使用单引号代替双引号
"prettier.proseWrap": "preserve", // 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
"prettier.arrowParens": "avoid", // (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
"prettier.bracketSpacing": true, // 在对象,数组括号与文字之间加空格 "{ foo: bar }"
"prettier.disableLanguages": ["ts"], // 不格式化ts文件,ts文件的格式化单独设置
"prettier.endOfLine": "auto", // 结尾是 \n \r \n\r auto
"prettier.eslintIntegration": false, //不让prettier使用eslint的代码格式进行校验
"prettier.htmlWhitespaceSensitivity": "ignore",
"prettier.ignorePath": ".prettierignore", // 不使用prettier格式化的文件填写在项目的.prettierignore文件中
"prettier.jsxBracketSameLine": false, // 在jsx中把'>' 是否单独放一行
"prettier.jsxSingleQuote": false, // 在jsx中使用单引号代替双引号
"prettier.parser": "babylon", // 格式化的解析器,默认是babylon
"prettier.requireConfig": false, // Require a 'prettierconfig' to format prettier
"prettier.stylelintIntegration": false, //不让prettier使用stylelint的代码格式进行校验
"prettier.trailingComma": "es5", // 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
"prettier.tslintIntegration": false // 不让prettier使用tslint的代码格式进行校验
}
//直接使用prettier下的方法就行
{
"printWidth": 80,
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 4,
"proseWrap": "never",
"overrides": [{ "files": ".prettierrc", "options": { "parser": "json" } }],
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-packagejson"]
}
5.自定义配置Config
如果不需要自定义Config 根目录自带的.Umirc.ts就够用了
import { defineConfig } from "umi";
export default defineConfig({
routes: [
{ path: "/", component: "index" },
{ path: "/docs", component: "docs" },
],
npmClient: 'yarn',
});
当需要自定义Config时,多环境下
在根目录新建config文件夹,文件夹内新增配置,图中分为dev测试和proc正式。config.js文件是公共配置这里需求辅助修改package.json文件
修改package.json
注:环境配置需要安装cross-env依赖
修改环境配置config.dev.js
export default {
title: '这里是项目名称',
favicons: ['/circleLogo.svg'],//浏览器小图标图标地址,对应public下的资源
define: {
'process.env.BASEURL': 'http://47.96.9.139:8081',//请求环境的地址
},
};
修改公用config.js
注:使用plugins中的@umijs/plugins需要安装@umijs/plugins的依赖
antd 需要直接安装antd
使用rem需要安装postcss-pxtorem的依赖
使用vw需要安装postcss-px-to-viewport-8-plugin的依赖
import { defineConfig } from 'umi';
import pxtorem from 'postcss-pxtorem' // rem的插件
//import pxToViewport from 'postcss-px-to-viewport-8-plugin';//vw插件,移动端
export default defineConfig({
title: '这里是项目名称',
plugins: ['@umijs/plugins/dist/dva', '@umijs/plugins/dist/antd'],//第一个是在项目中使用dev,第二个是使用antd
// theme: { '@primary-color': '#1DA57A' },//所有的主题色
dva: {//dva的配置
immer: {
enableES5: true,
enableAllPlugins: true,
},
},
externals: {},
publicPath: '/',//路由前缀
base: '/',
headScripts: [{ src: '/autoSize.js' }],//head中需要读取的js,这里的autoSize是rem转化算法的js
antd: {
//5.0.0直接这样舍弃了配置
},
extraPostCSSPlugins: [//rem的转化,这里也可以是vw
pxtorem({
rootValue: 100,
propList: ['*'],
}),
// pxToViewport({
// viewportWidth: 375, // 根据设计稿修改
// include: [//src//],
// }),
],
});
6.全局样式
在src下创建global.less 或者global.scss
这里写入的是全局共用样式,可以包括颜色,字体大小等等
@import './font.less'; // 全局字体样式
html,
body,
#root {
height: 100%;
margin: 0;
font-family: 'MiSans-Regular';
}
.modalBtn {
width: 77px;
height: 40px;
font-family: 'MiSans-Medium';
margin-right: 4px;
letter-spacing: 0.1px;
}
.cancelBtn {
// 取消按钮
width: 77px;
height: 40px;
border: 2px solid black;
font-family: 'MiSans-Medium';
letter-spacing: 0.1px;
}
7.字体文件,head需要加载的js存放
在根目录创建public文件夹,所有的字体文件都放在fonts文件夹下,js读取文件以及ico图标都放在平级
创建字体样式,在src下创建font.less 或者font.scss
这里引入的public下的fonts,前缀和config配置中publicPath有关,这里可以多个字体
@font-face {
font-family: 'MiSans-Regular';
font-size:24px;
font-weight:500;
src: url('/fonts/MiSans-Regular.ttf');
}
@font-face {
font-family: 'MiSans-Medium';
src: url('/font/MiSans-Medium.ttf');
}
8.静态资源文件
在src下新建一个assets文件里面可以新建一个imgs文件夹用来存放所有静态资源图片
9.请求Api的使用以及其它项目共用方法
注:需要安装axios依赖
在src下新建utils文件夹
common.js
用来存放公用的js方法,例如本地cookie存储,代码块中相关依赖别忘记安装
import Cookies from 'js-cookie';
export function setCookie(name, val) {
Cookies.set(name, val, { expires: 30, path: '/' });
}
export function getCookie(name) {
return Cookies.get(name);
}
export function getCookieJSON(name) {
return Cookies.getJSON(name);
}
export function removeCookie(name) {
Cookies.remove(name);
}
export function getUserInfo() {
return Cookies.getJSON('userInfo') || {};
}
request.js
请求Api封装
import { getUserInfo, removeCookie } from './common';
import { message } from 'antd';
import { history } from 'umi';
import axios from 'axios';
import qs from 'qs';
axios.interceptors.request.use(
function (config) {
const { headers, ...rest } = config;
return {
...rest,
paramsSerializer: function (params) {
return qs.stringify(params, { arrayFormat: 'repeat' });
},
headers: {
Authorization: getUserInfo().accessToken ? `${getUserInfo().accessToken}` : null,
...headers,
},
};
},
function (error) {
return Promise.reject(error);
},
);
axios.interceptors.response.use(function (response) {
const data = response.data;
if (data?.code) {
if (data.code == 400) {
message.error(data.message);
}
else if (data.code == 401) {
//token过期强制刷新页面
message.error({ content: '请先登陆', key: 'login' });
return data
}
else if (data.code == 200) {
return data;
}
}
}, function (error) {
return Promise.reject(error);
});
export default axios;
index.js
用来暴露request和common文件
import request from './request';
import * as common from './common';
export {request,common};
10.相关Service声明
在src下新建services文件夹,默认新建一个commonService.js和index.js
commonService.js存放公用的请求接口
index.js用来暴露接口定义
import { request } from '@/utils';
export function getCustomerSelectOptions(option) {
return request(`${process.env.BASEURL}/work/chooseCustomer`, {
method: 'get',
...option,
});
}
export function getProjectSelectOptions(option) {
return request(`${process.env.BASEURL}/work/chooseProject`, {
method: 'post',
...option,
});
}
export function deleteRole(option) {
return request(`${process.env.BASEURL}/permission/role/delete`, {
method: 'delete',
...option,
});
}
注:所有接口文件命名规范都需要跟“Service”
import * as commonService from './commonService';
export { commonService };
11.dva的使用以及页面函数调用规范
公用models
在src下新建一个models文件夹,文件夹里新建common.js文件,用来存放公用请求
import { commonService } from '@/services/index';
import { message } from 'antd';
import { history } from 'umi';
const Model = {
namespace: 'common',
state: {
},
effects: {
},
reducers: {
update(state, { payload }) {
return {
...state,
...payload,
};
}
},
};
export default Model;
页面级别的models
每个页面级别都有一个models,用来控制当前页面内的store
import { loginService } from '@/services/index';
import { common } from '@/utils';
import { message } from 'antd';
import { history } from 'umi';
export default {
namespace: 'login',
state: {
},
effects: {
*logout({ payload }, { call, put, select }) {
const res = yield call(loginService.logout, { params: {} });
if (res.code === 200) {
common.removeCookie('userInfo')
yield put({ type: 'update', payload: { userInfo: {} } })
history.push('/login')
}
},
},
reducers: {
update(state, { payload }) {
return {
...state,
...payload,
};
}
},
};
页面内调用函数规范
import React, { useEffect, useState } from 'react';
import styles from './index.less';
import { connect, history, Outlet, useLocation } from 'umi';
const Index = ({ currentkey,onUpdate ,getUserInfo}) => {
return (
<>
<div className={styles.management}>
{currentkey}
</div>
</>
);
}
function mapStateToProps({ loading, common }) {
return {
currentkey: common.currentkey,
};
}
function mapDispatchToProps(dispatch) {
//此处写所有函数调用
return {
onUpdate(payload) {
dispatch({ type: 'common/update', payload })
},
getUserInfo(payload) {
return dispatch({ type: 'login/getUserInfo', payload })
}
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Index);
12.项目构建打包
这两个一个是测试环境打包,一个是正式,当然你可以配置更多环境,只要有对应的config就可以
成功后根目录会生成dist文件夹
"build-dev": "cross-env UMI_ENV=dev umi build",
"build-proc": "cross-env UMI_ENV=proc umi build",
13.其它相关规范
- 页面内避免使用useState
- 页面代码过长切分成多个业务组件
- 当存在公用模块时,统一在src下新建components文件夹同时创建相关custom组件
- 所有的列表页面都需要loading,包括提交按钮,针对接口做监听
- 严禁在项目中使用定时器
- 去除所有console.log
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
2022-12-28 2022年总结-五年的时间才明白业务的重要性
2022-12-28 .net core-利用PdfSharpCore 操作PDF实例
2022-12-28 Remix 1.9 发布,全栈框架
2022-12-28 微软工程师展望 Rust 2023:重写编译器、解决管理问题
2022-12-28 Visual Studio 现已内置 Markdown 编辑器
2018-12-28 vue数组中对象属性变化页面不渲染问题