Umi4最佳实践(个人向)

Umi4最佳实践(个人向)

2023-02-273,888阅读6分钟
 
 
智能总结
复制
重新生成
 

这篇文章是关于 Umi4 的个人最佳实践,涵盖新建项目文件夹、安装框架依赖、启用 Prettier 及相关属性配置、自定义 Config、全局样式设置、字体和静态资源处理、请求 Api 及共用方法、页面函数调用规范、项目构建打包和其它相关规范等内容。

关联问题:umi4如何优化性能怎样配置多环境umi4打包注意啥
 
 

非Max版本

1.新建项目文件夹进入对应的文件夹
 
bash
代码解读
复制代码
mkdir 文件夹名称 && cd 文件夹名称

//此处specification为例子

mkdir specification && cd specification
2.安装umi框架依赖
 
sql
代码解读
复制代码
npx create-umi@latest

或

yarn create umi

//注:如果没有yarn 需要通过npm i yarn -g 全局安装

3.启用 Prettier(前端代码格式化工具)
 
lua
代码解读
复制代码
pnpm umi g

✔ Pick generator type › Enable Prettier -- Enable Prettier

项目中会自动生成文件

4.了解和使用prettier的属性
 
json
代码解读
复制代码
/*  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的代码格式进行校验
}
 
json
代码解读
复制代码
//直接使用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就够用了

 
php
代码解读
复制代码
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
 
arduino
代码解读
复制代码
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的依赖

 
php
代码解读
复制代码
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

这里写入的是全局共用样式,可以包括颜色,字体大小等等

 
css
代码解读
复制代码
@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有关,这里可以多个字体

 
css
代码解读
复制代码
@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存储,代码块中相关依赖别忘记安装

 
javascript
代码解读
复制代码
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封装

 
javascript
代码解读
复制代码
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文件

 
javascript
代码解读
复制代码
import request from './request';
import * as common from './common';

export {request,common};
10.相关Service声明

在src下新建services文件夹,默认新建一个commonService.js和index.js

commonService.js存放公用的请求接口

index.js用来暴露接口定义

 
javascript
代码解读
复制代码
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”

 
javascript
代码解读
复制代码
import * as commonService from './commonService';
export { commonService };
11.dva的使用以及页面函数调用规范
公用models

在src下新建一个models文件夹,文件夹里新建common.js文件,用来存放公用请求

 
javascript
代码解读
复制代码
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

 
javascript
代码解读
复制代码
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,
      };
    }
  },
};
页面内调用函数规范
 
javascript
代码解读
复制代码
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文件夹

 
json
代码解读
复制代码
"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

posted on   漫思  阅读(67)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 微软正式发布.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数组中对象属性变化页面不渲染问题

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示