前言:umi项目越来越受到越多人的喜爱,为什么会这个样子?那肯定是umi有自己强大的地方。比如内置了react、ant design、等插件不需要我们再手动的安装。
一. 新建一个文件用于放置我们生成的umi项目然后执行
npm create @umijs/umi-app
会看到如下
Need to install the following packages:
@umijs/create-umi-app@3.5.38
Ok to proceed? (y)
此时键入y即可随后会看到
Ok to proceed? (y) y
npm WARN deprecated core-js@3.6.5: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.
Copy: .editorconfig
Write: .gitignore
Copy: .prettierignore
Copy: .prettierrc
Write: .umirc.ts
Copy: mock/.gitkeep
Write: package.json
Copy: README.md
Copy: src/pages/index.less
Copy: src/pages/index.tsx
Copy: tsconfig.json
Copy: typings.d.ts
此时我们的文件夹中就会出现我们新建的项目了
二. 开始配置我们的项目用于构建完整体系然后用于开发
- 拆分创建项目自动生成的
.umirc.ts
。为什么要这样子做?因为路由或者其他配置可能会很多,拆分出去后不会显得一个文件的内容很多,同时也会方便我们的归类和管理。
a. 在src
同级新建config
文件夹同时在下面新建config.js
用于抽离.umirc.ts
的项目配置部分
b. 在config
文件夹下面新建routes.js
用于抽离.umirc.ts
中的routes
部分
export default [
// 配置式路由
{
path: '/login',
component: '@/pages/login',
name: '登陆页',
// 在左边菜单栏不显示
hideInMenu: true,
},
{
path: '/mainMenu1',
name: '菜单1',
routes: [
{
path: '/mainMenu1/childMenu1',
component: '@/pages/mainMenu1/childMenu1',
name: '子菜单1-1',
},
{
path: '/mainMenu1/childMenu2',
component: '@/pages/mainMenu1/childMenu2',
name: '子菜单1-2',
},
{
path: '/mainMenu1/childMenu3',
component: '@/pages/mainMenu1/childMenu3',
name: '子菜单1-3',
},
],
},
];
c. 在config.js
文件里面引入routes.js
文件
import routes from './routes.js';
d. 删除.umirc.ts
,此时的.umirc.ts
文件已经没有任何作用了,已经被我们肢解了。注意.umirc.ts
的优先级比config
的优先级更高
e. 配置项目骨架,在config.js中加入如下代码即可
// 开启项目视图骨架配置
layout: {
// 支持任何不需要dom的
name: 'Ant Design',
locale: true,
layout: 'side',
},
最终的config.js
的文件
import { defineConfig } from 'umi';
import routes from './routes.js';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
// 配置开启antd组件库的使用
antd: {
dark: false, // 开启暗黑主题
},
routes,
fastRefresh: {},
// 开启项目视图骨架配置
layout: {
// 支持任何不需要dom的
name: 'Ant Design',
locale: true,
layout: 'side',
},
});
效果图

- 配置一级菜单栏的菜单图标
a. 如果我们想使用ant design
里面提供的图标找到图标的名字然后写入即可
b. 如果我们觉得ant design
提供的图标不是我们想要的怎么办? 在src
同级新建public
文件夹用于存放我们项目中的静态资源文件我这里新建了public
文件夹并且在public
文件夹下面新建了icons
文件夹用于存放图标
path: '/',
component: '@/pages/home',
name: '首页',
// 如果要使用ant design里面的icon直接写icon的名字即可
icon: 'setting',
// 使用自定义图标
// icon: '/icons/menu-uw.svg',
效果图

- 配置用于控制菜单的权限
3-1. 在src
下面新建access.js/access.ts
我们约定了 src/access.ts 为我们的权限定义文件,该文件需要默认导出一个方法,导出的方法会在项目初始化时被执行。该方法需要返回一个对象,对象的每一个值就对应定义了一条权限。如下所示:
export default function access(initialState) {
// menu上的值需要一个初始值,undefined会默认显示菜单
return {
home: true,
mainMenu1: true,
childMenu1: true,
childMenu2: false,
childMenu3: false,
mainMenu2: true,
childMenu4: true,
childMenu5: false,
childMenu6: false,
};
}
效果图

3-2. 通过接口获取权限该怎么处理?
在
src
下面新建app.js/app.ts
const initialState = {
permissions: {
home: true,
mainMenu1: true,
childMenu1: true,
childMenu2: true,
childMenu3: true,
mainMenu2: true,
childMenu4: true,
childMenu5: true,
childMenu6: true,
},
};
export async function getInitialState() {
// Promise.all([
// salesList(), // 接口请求事件
// goodsList(),
// ]).then(([salesGoods, allGoods]) => {
// Object.assign(initialState, {
// salesgoodsList: salesGoods?.data,
// allgoodsList: allGoods?.data,
// });
// });
return initialState;
}
在access.js/access.ts
中引入
export default function access(initialState: any) {
const { permissions } = initialState || {};
// menu上的值需要一个初始值,undefined会默认显示菜单
return {
home: true,
mainMenu1: true,
childMenu1: true,
childMenu2: false,
childMenu3: false,
mainMenu2: true,
childMenu4: true,
childMenu5: false,
childMenu6: false,
...permissions,
};
}
也可以在tsx页面中使用
import { useModel, useAccess } from 'umi';
const {
initialState,
loading, // getInitialState 是否处于 loading 状态,在首次获取到初始状态前,页面其他部分的渲染都会被阻止。loading 可用于判断 refresh 是否在进行中。
error, // 当运行时配置中,getInitialState throw Error 时,会将错误储存在 error 中。
refresh, // 重新执行 getInitialState 方法,并获取新数据。相当于刷新了一遍初始化数据,但是页面无感知。// refresh()
setInitialState, // 手动设置 initialState 的值,手动设置完毕会将 loading 置为 false. // setInitialState({ ...initialState, allgoodsList: data })
} = useModel('@@initialState');
console.log('initialState', initialState);
或
const access = useAccess();
console.log('access', access);
注意:useAccess
专用于获取权限信息,而使用useModel
可以获取所有全局的变量
3-3. 配置多环境打包机制
安装插件
npm install --save-dev cross-env
在config文件夹下新建config.dev.ts
, config.prod.ts
文件
config.dev.ts
export default {
define: {
'process.env': {
NODE_ENV: 'dev',
},
}
}
config.prod.ts
export default {
define: {
'process.env': {
NODE_ENV: 'prod',
},
}
}
package.json
配置不同环境打包命令
"scripts": {
"start": "umi dev",
"build": "umi build",
"build:dev": "cross-env NODE_ENV=dev umi build",
"build:prod": "cross-env NODE_ENV=prod umi build",
"postinstall": "umi generate tmp",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
三. 安装一些插件协助我们开发
- 生产环境去掉调试使用的
console.log()
1-1 安装插件
2-2 在config.prod.ts
中使用
# 安装 `babel-plugin-transform-remove-console` 插件
npm i -D babel-plugin-transform-remove-console
import { defineConfig } from 'umi';
export default defineConfig({
// 配置是否让生成的文件包含 hash 后缀,通常用于增量发布和避免浏览器加载缓存。
hash: true,
extraBabelPlugins: ['transform-remove-console'],
define: {
// 重点就是这个属性了,设置全局变量
// 在项目中,可以通过process.env.NODE_ENV 或者
// process.env.UMI_ENV 或者process.env.date得到对应环境的值
'process.env': {
NODE_ENV: 'prod',
UMI_ENV: 'prod',
date: '2023-03-17',
},
},
});
- 使用less书写页面样式
注意:umi已内置less直接使用即可无需安装
example:
import lessStyles from './index.less';
import sassStyles from './index.sass';
import scssStyles from './index.scss';
export default function () {
return <div className={lessStyles.title}>
Hello World
<p className={sassStyles.blue}>I am blue</p>
<p className={scssStyles.red}>I am red</p>
</div>;
}
- 配置用于请求的代理
在config.dev.ts中加入
proxy: {
'/api': {
target: 'http://jsonplaceholder.typicode.com/',
changeOrigin: true,
pathRewrite: { '^/api': '' },
},
},
- 封装request用于发起真正的请求
网友评论