文章目录
- umi介绍
- umi是什么?
- umi的特性
- 开发环境
- Node.js
- 依赖管理工具
- 目录结构
- 路由
- 配置路由
- 页面跳转
- Link组件
- 路由组件参数:
- 路由动态参数
- query信息
- 样式
- 使用css样式
- dva
- 为什么需要状态管理
- umi如何管理状态
umi介绍
umi是什么?
Umi,中文发音为「乌米」,是可扩展的企业级前端应用框架。Umi 以路由为基础的,同时支持配置式路由和约定式路由,保证路由的功能完备,并以此进行功能扩展。然后配以生命周期完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
umi的特性
开发环境
Node.js
Umi.js需要使用Node.js来进行开发,首先需要确保电脑已经安装了Node.js且版本在14以上。
依赖管理工具
Node安装完成后会自带npm依赖管理工具,但是Umi推荐使用
pnpm作为依赖管理工具
目录结构
根目录下
package.json
包含插件和插件集
.env
环境变量,比如:
PORT=8888
COMPRESS=none
.umirc.ts
与 config/config.ts文件功能相同, .umirc.ts文件优先级更高
配置文件,包含umi内置功能和插件的配置
config/config.ts
与 .umirc.ts文件功能相同,.umirc.ts文件优先级更高
配置文件,包含umi内置功能和插件的配置
dist目录
执行umi build后,产物会默认存到这里。可以通过配置修改产物的输出路径。
mock目录
存储mock文件,此目录下所有js和ts文件都会被解析为mock文件。用于本地的模拟数据服务。
public目录
此目录下所有文件会被copy到输出路径
src目录
.umi目录
dev时的临时文件目录,比如入口文件、路由等,都会被临时生成到这里。不要提交.umi目录到git仓库,他们会在umi dev时被删除并重新生成。
路由
配置路由
在配置文件中通过routes进行配置,格式是路由信息的数组。
比如
export default {
routes: [
{ path: '/', component: 'index' },
{ path: '/user', component: 'user' },
],
}
path
type:字符串
path只支持两种占位符配置,动态参数 :id 的形式、* 通配符,通配符只能出现在路由字符串的最后
以下是支持的路由路径配置形式
/groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*
以下是不支持的路由配置形式:
/users/:id?
/tweets/:id(\d+)
/files/*/cat.jpg
/files-*
component
type:string
配置location和path匹配后用于渲染的react组件路径,可以是绝对路径,也可以是相对路径,如果是相对路径,会从 src/pages开始找起。
src可以用@代替。
routes
配置子路由,格式为路由数组
比如:
export default {
routes: [
{ path: '/login', component: 'login' },
{
path: '/',
component: '@/layouts/index',
routes: [
{ path: '/list', component: 'list' },
{ path: '/admin', component: 'admin' },
],
},
],
}
然后在src/laouts/index中通过渲染子路由
import {Outlet} from 'umi'
export default (props) => {
return <div style={{ padding: 20 }}>
<Outlet/>
</div>;
}
这样,访问 /list和/admin就会带上 src/layouts/index这个layout组件。
redirect
type:string
路由重定向
比如:
export default {
routes: [
{ path: '/', redirect: '/list' },
{ path: '/list', component: 'list' },
],
}
访问 / 时会重定向到 /list,并由src/pages/list 文件进行渲染。
wrappers
type:string[]
配置路由组件的包装组件,通过包装组件可以为当前的路由组件结合更多的功能。比如,可以用于路由级别的权限校验:
export default {
routes: [
{ path: '/user', component: 'user',
wrappers: [
'@/wrappers/auth',
],
},
{ path: '/login', component: 'login' },
]
}
然后在 src/wrappers/auth中
import { Navigate, Outlet } from 'umi'
export default (props) => {
const { isLogin } = useAuth();
if (isLogin) {
return <Outlet />;
} else{
return <Navigate to="/login" />;
}
}
这样,访问/user,就通过auth组件做权限校验,如果通过,渲染src/pages/user,否则跳转到 /login
title
type:string
配置路由的标题
页面跳转
使用 history 或者 useNavigate进行跳转
Link组件
比如:
import { Link } from 'umi';
export default () => (
<div>
<Link to="/users">Users Page</Link>
</div>
);
点击 Users page 就会跳转到 /users 地址
路由组件参数:
match信息
useMatch
location信息
useLocation
路由动态参数
useParams
query信息
useSearchParams
样式
使用css样式
你可以在umi项目中使用 .css文件声明各种样式,然后在.js文件中引入即可生效。
按照此种引入方式的样式会在整个umi项目中生效,即无论你从哪个 .js文件引入,他声明的样式可以在任何页面和组件中使用。如果你想避免这种情况,可以使用 css modules的功能来限制样式的作用域
使用css Modules
在js文件中引入样式时,赋予他一个变量名,就可以将样式以 css module的形式引入。
import styles from './index.css';
export default function () {
return <div className={styles.title}>
Hello World
</div>;
}
上面示例中,index.css文件中声明的样式不会对全局样式早成影响,他的作用域仅仅是该js文件。
dva
为什么需要状态管理
react的组件只是通过jsx以及样式按照state构建最终的UI,真正将页面动态化的实际上是state的变化实现的。对于简单的前端应用,在组件中通过组件自身的state加上父组件传过来的props就能够满足应用数据管理的需求,但是当应用膨胀到一定程度后就会导致组件内维护的状态非常复杂,加上组件之间的状态传递,很容易导致数据管理混乱。很小的改动都可以导致难以预料的副作用。
umi如何管理状态
umi内置了dva提供了一套状态管理方案
数据统一在 src/models 中的model管理,组件内尽可能的不去维护数据,而是通过connect去关联model中的数据。页面有操作的时候则触发一个action去请求后端接口以及修改model中的数据,将业务逻辑分离到一个环形的闭环中。使得数据在其中单向流动。让应用更好的进行维护。