背景
image.png之前GMTC 全球大前端技术大会上,公开了这张阿里前端框架的时间线,我们可以看到,在2017.8和2017.12,阿里两个不同的业务部门曾接连推出了两款前端框架,Umi和Bigfish。但是在2018.6,阿里对两个部门进行了整合,产出了Umi+Bigfish这样的整合框架。在2019.11月,Umi这款框架才算最终落地,经过了两年的整合,我们来看看这个Umi框架到底是个什么黑科技产品
它是什么
image.png从大会上放出的另一张图我们看到了,我们在“刀耕火种”的时代做前端开发的时候,总是会考虑我们选择在项目里使用 React 库来开发的时候,项目的数据流方案应该怎么选择(redux, mobx, redux-saga, redux-router,dva,等),组件库 的选择(antd, material design),以及webpack打包的复杂配置等,这里的 Bigfish&um看起来像是把以前我们项目中通常会用到的一些库整合到了一起。
既然Umi是一个框架,那就有很多“约定”的规则,需要我们遵守,不管是在路由配置,还是在mock数据,以及数据和页面交互方面,我们都能够感受到这种潜在的“约定”。
它有什么
Umi概述幕布版链接
之前用幕布整理了一个其中大概的内容,而且2.x与3.x版本差别还比较大,这张图片整理的大部分是基于2.x的版本,可以粗略的看看,也可以点击链接去官网查看,Umi官网
它怎么用
我这里用Umi做了一个很简陋的应用,不过基本需要包括的路由,异步请求,页面跳转和mock数据都用到了,这里就拆分一下给大家做个演示。
登陆
image.png这是一个很正常的登陆表单,表单的UI和验证部分都是直接从Umi提供的工作台上找到的基于antd的区块,添加进项目就可以用,非常方便,只需要修改表单登陆事件处理的函数:
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
this.props.form.validateFields((err: any, values: any) => {
if (!err) {
this.props.dispatch({
type: 'users/login',
payload: values,
});
}
});
};
这里就要提到Umi推荐使用的数据流方案Dva,它封装并简化了redux、redux-router、redux-saga的使用难度,具体想了解更多Dva的更多内容,可以访问Dva官网。
在代码中,可以看到这里使用了redux常用的dispatch action的方式来发起登录请求。所以我们需要有一个地方能够handle这个action的执行,接下来看对应的modal是如何实现的:
export default {
namespace: 'users',
state: {
id: '',
userName: '',
friends: [],
},
reducers: {
save: (state: UserState, { payload }: { payload: UserState }) => {
return { ...state, ...payload };
},
},
effects: {
*login({ payload }: { payload: LoginRequestParams }, { call, put }: EffectsCommandMap) {
const response = yield call(loginApi, payload)
yield put({ type: 'save', payload: response });
router.push('/users');
}
},
};
在modal中我们定义了这个modal的namespace叫做users
,里面存放的数据包含id
,userName
和friends
,定义了一个叫做save
的reducer
来保存相关数据,还定义了一个叫做login
的方法来做含有副作用的操作,可以看到方法中接收到payload
以后调用了call
方法来执行了一个loginApi
,数据获取成功后,发起save
操作来保存返回的数据,然后通过router.push
来更改路由。其中有很多Dva相关的知识,感兴趣的朋友可以去了解下。再贴上loginApi中做的事情:
export const loginApi = (payload: LoginRequestParams) => {
return fetch("http://localhost:8000/api/users", {
method: "POST",
body: JSON.stringify(payload)
}).then((response: Response) => response.json())
};
这里直接请求了localhost
接口的原因是我并没有做后端Api,所以是用了Umi本身提供的mock功能
使用mock数据来模拟应用的后端访问。至此,一个完整的login登录流程就出来了。当我们点击login的时候,打开Chrome的redux插件:
store变化
可以看到这里有我们完整的action flow
,以及我们的state的变化。
当我们将数据存储起来以后,我们在组件中如何使用store中的数据的方式和redux类似,通过dva提供的connect方法,传入mapStateToProps参数即可,如:
const mapStateToProps = ({ users }: { users: UserState }) => ({
userName: users?.userName,
friends: users?.friends,
});
export default connect(mapStateToProps)(WelcomePage);
路由
在上面的代码已经看到了我们路由跳转的一种方法是通过Umi提供的router.push(url)
,官方还提供一种是通过链接跳转,<Link to="/user">
这种方式。
在Umi中有两种方式来定义路由,一种是约定式,一种是配置式。接下来就说一下这两种的区别:
约定式
src目录结构我们在使用脚手架生成Umi项目后可以看到src的目录里面包含了一个pages的文件夹,umi打包的时候会将目录之间的关系映射成路由关系,如:
-
src/pages/users/index.tsx
会成为/users
-
src/pages/users/$id.tsx
会成为/users/:id
-
src/pages/users/[id]/settings.tsx
会成为/users/:id/settings
以此类推。umi打包后生成的pages/.umi/router.js
文件也可以看出来它们之间的关系,如图:
...,
routes: [
{
path: '/404',
exact: true,
component: __IS_BROWSER
? _dvaDynamic({
component: () => import('../404.tsx'),
})
: require('../404.tsx').default,
_title: 'umi-js',
_title_default: 'umi-js',
},
{
path: '/',
exact: true,
component: __IS_BROWSER
? _dvaDynamic({
component: () => import('../index.tsx'),
})
: require('../index.tsx').default,
_title: 'umi-js',
_title_default: 'umi-js',
},
配置式
如果项目路由足够复杂,有很多权限校验的东西,那么Umi也提供了配置化修改。在项目中会有一个.umirc.ts
的文件,这个文件就是项目的配置文件,也可以通过config/config.ts
文件来配置。
const config: IConfig = {
routes: [
{ path: '/', component: './index' },
{
path: '/users',
component: './users/index',
},
{
path: 'users/detail',
component: './users/detail',
},
{ path: 'users/:id', component: './users/$id.tsx' },
],
...,
};
在配置文件里我们可以更灵活的定义我们路由,也可以添加权限路由和嵌套路由,这里就不赘述了,有兴趣可以访问官网查看。
mock数据
当我们做前后端分离项目的时候,前后端通常不会一直都以相同速率开发,总是会有一方等待另一方集成的问题。在umi中针对这种情况给了mock数据的解决方案,如图:
根目录
在根目录中有一个叫做mock的文件夹,Umi约定在这个文件夹下的文件都被视作mock数据。当前端访问本地接口的时候,就会到这里面来对应的查找有没有和请求的url能够匹配的数据,如果有就直接返回。
比如我的api.js文件中:
import mockjs from 'mockjs';
export default {
'POST /api/users': mockjs.mock({
userName: '@name',
id: '@id',
'friends|5-10': [{ id: '@id', userName: '@name' }],
}),
};
这里使用了mockjs
来生成对应格式的mock数据,这样可以最大限度的保证数据的有效性。
Umi-UI
这里有一个Umi的工作台觉得需要提出来说一下,因为个人觉得这个工作台很大程度上减少了前端开发的门槛。
配置模块
任务模块
资产模块
从上面的图可以看出,如果你不熟悉webpack
,不熟悉配置式路由
,不熟悉npm script
,在这个工作台都能够可视化修改。甚至你可以直接把区块和模板里的东西直接引入到你自己的项目中,无须做太多改动就可用,极大减轻了UI开发的压力。
结语
以上就是对Umi框架的一些简单的介绍,可能大家觉得Umi 2.x有点臃肿,包含的东西太多。没关系,可以尝试Umi 3.0,更加的精简和插件化。
最后附上项目的github地址。
网友评论