共计 4253 个字符,预计需要花费 11 分钟才能阅读完成。
umi,中文可发音为乌米,是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持类 next.js 的约定式路由,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载。然后配以完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求,目前内外部加起来已有 50+ 的插件
1.Why umi
开箱即用,内置 react、react-router 等
类 next.js 且功能完备的路由约定,同时支持配置的路由方式
完善的插件体系,覆盖从源码到构建产物的每个生命周期
一键兼容到 IE9
完善的 TypeScript 支持
与 dva 数据流的深入融合
2.umi 项目结构
.
├── dist/ // 默认的 build 输出目录
├── mock/ // mock 文件所在目录,基于 express
├── config/
├── config.js // umi 配置,同 .umirc.js,二选一
└── src/ // 源码目录,可选
├── layouts/index.js // 全局布局
├── pages/ // 页面目录,里面的文件即路由
├── .umi/ // dev 临时目录,需添加到 .gitignore
├── .umi-production/ // build 临时目录,会自动删除
├── document.ejs // HTML 模板
├── 404.js // 404 页面
├── page1.js // 页面 1,任意命名,导出 react 组件
├── page1.test.js // 用例文件 umi test 会匹配所有 .test.js 和 .e2e.js 结尾的文件
└── page2.js // 页面 2,任意命名
├── global.css // 约定的全局样式文件,自动引入,也可以用 global.less
├── global.js // 可以在这里加入 polyfill
├── .umirc.js // umi 配置,同 config/config.js,二选一
├── .env // 环境变量
└── package.json
3. 约定式路由
启动 umi dev 后,大家会发现 pages 下多了个 .umi 的目录请不要直接在这里修改代码,umi 重启或者 pages 下的文件修改都会重新生成这个文件夹下的文件,约定 pages 下所有的 (j|t)sx? 文件即路由
1. 基础路由
// 假设 pages 目录结构如下:
1. pages/
2. users/
– index.js
– list.js
3. index.js
// 那么,umi 会自动生成路由配置如下
[
{path: ‘/’, component: ‘./pages/index.js’},
{path: ‘/users/’, component: ‘./pages/users/index.js’},
{path: ‘/users/list’, component: ‘./pages/users/list.js’},
]
2. 动态路由
+ pages/
+ $post/
– index.js
– comments.js
+ users/
$id.js
– index.js
[
{path: ‘/’, component: ‘./pages/index.js’},
{path: ‘/users/:id’, component: ‘./pages/users/$id.js’},
{path: ‘/:post/’, component: ‘./pages/$post/index.js’},
{path: ‘/:post/comments’, component: ‘./pages/$post/comments.js’},
]
3. 可选的动态路由
+ pages/
+ users/
– $id$.js
– index.js
[
{path: ‘/’: component: ‘./pages/index.js’},
{path: ‘/users/:id?’: component: ‘./pages/users/$id$.js’},
]
4. 嵌套路由
umi 里约定目录下有 _layout.js 时会生成嵌套路由,以 _layout.js 为该目录的 layout
+ pages/
+ users/
– _layout.js
– $id.js
– index.js
———-
[
{path: ‘/users’, component: ‘./pages/users/_layout.js’,
routes: [
{path: ‘/users/’, component: ‘./pages/users/index.js’},
{path: ‘/users/:id’, component: ‘./pages/users/$id.js’},
],
},
]
4. 路由跳转
1. 声明式
import Link from ‘umi/link’;
export default () => (
<Link to=”/list”>Go to list page</Link>
);
2. 命令式
import router from ‘umi/router’;
function goToListPage() {
router.push(‘/list’);
}
3.connect 后路由切换后没有刷新用 withRouter
import withRouter from ‘umi/withRouter’;
export default withRouter(connect(mapStateToProps)(LayoutComponent));
5.Use umi with dva
特性
按目录约定注册 model,无需手动 app.model
文件名即 namespace,可以省去 model 导出的 namespace key
无需手写 router.js,交给 umi 处理,支持 model 和 component 的按需加载
内置 query-string 处理,无需再手动解码和编码
内置 dva-loading 和 dva-immer,其中 dva-immer 需通过配置开启
开箱即用,无需安装额外依赖,比如 dva、dva-loading、dva-immer、path-to-regexp、object-assign、react、react-dom 等
1..umirc.js 里配置插件(或者在 config 里配置)
xport default {
plugins: [
[
‘umi-plugin-react’,
{
dva: true,
},
]
],
};
2.model 注册
model 分两类,一是全局 model,二是页面 model。全局 model 存于 /src/models/ 目录,所有页面都可引用;页面 model 不能被其他页面所引用。规则如下:
src/models/*/.js 为 global model
src/pages//models//*.js 为 page model
global model 全量载入,page model 在 production 时按需载入,在 development 时全量载入
page model 为 page js 所在路径下 models/*/.js 的文件
page model 会向上查找,比如 page js 为 pages/a/b.js,他的 page model 为 pages/a/b/models//.js + pages/a/models//.js,依次类推
约定 model.js 为单文件 model,解决只有一个 model 时不需要建 models 目录的问题,有 model.js 则不去找 models/*/.js
+ src
+ models
– g.js// 全局 model 可共用
+ pages
+ a//a 的 page model 为 src/pages/a/models/{a,b,ss/s}.js
+ models
– a.js
– b.js
+ ss
– s.js
– page.js
+ c//c 的 page model 为 src/pages/c/model.js
– model.js
+ d//c/d 的 page model 为 src/pages/c/model.js, src/pages/c/d/models/d.js
+ models
– d.js
– page.js
– page.js
6.Umi 配置路由方式生成路由连接和加载 model
1. 在 config 文件目录下的 config.router.js 配置相关参数
{
name: ‘ 基础数据 ’,
icon: ‘table’,
path: ‘/basicData’,
routes: [
{
path: ‘basicData/list’,
name: ‘ 数据列表 ’,
component: ‘./BasicData/BasicList’,
}
]
},
2. 在 pages 文件下建好文件,全局 model 直接写到 src/models 下面,页面 model 写到 pages/ 页面 /models
3.umi 会自动生成相关的路由及其 model 的(在.umi 的 router.js 下面自动生成代码)
{
“name”: “ 基础数据 ”,
“icon”: “table”,
“path”: “/basicData”,
“routes”: [
{
“path”: “/basicData/list”,
“name”: “ 数据列表 ”,
“component”: _dvaDynamic({
app: window.g_app,
models: () => [
import(‘/home/jianjiacheng/WebstormProjects/Antd_Pro_UMI_JS_FrameWork/src/pages/BasicData/models/basicDataModal.js’).then(m => { return { namespace: ‘basicDataModal’,…m.default}})
],
component: () => import(‘../BasicData/BasicList’),
LoadingComponent: require(‘/home/jianjiacheng/WebstormProjects/Antd_Pro_UMI_JS_FrameWork/src/components/PageLoading/index’).default,
}),
“exact”: true
},
{
“component”: () => React.createElement(require(‘/home/jianjiacheng/WebstormProjects/Antd_Pro_UMI_JS_FrameWork/node_modules/_umi-build-dev@1.3.5@umi-build-dev/lib/plugins/404/NotFound.js’).default, {pagesPath: ‘src/pages’, hasRoutesInConfig: true})
}
]
},