框架
一、简介
收款定制开发是蚂蚁金服的底层前端框架,收款定制开发是可扩展的企业级前端应用框架。Umi 收款定制开发以路由为基础的,收款定制开发同时支持配置式路由和收款定制开发约定式路由,收款定制开发保证路由的功能完备,收款定制开发并以此进行功能扩展。收款定制开发然后配以生命周期完善收款定制开发的插件体系,收款定制开发覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。
二、特点
- 可扩展: Umi 实现了完整的生命周期,并使其插件化,Umi 内部功能也全由插件完成。此外还支持插件和插件集,以满足功能和垂直域的分层需求。
- 开箱即用: Umi 内置了路由、构建、部署、测试等,仅需一个依赖即可上手开发。并且还提供针对 React 的集成插件集,内涵丰富的功能;
- **完备路由:**同时支持配置式路由和约定式路由,同时保持功能的完备性,比如动态路由、嵌套路由、权限路由等等。
- 兼容性低: 不支持 IE 8 及以下浏览器,不支持 React 16.8.0 以下的 React,不支持Node 10 以下的环境;
三、快速上手
1.全局安装umi
// 先查看是否安装了node,确保node版本是8.10及以上。node -v // 使用yarn全局安装umiyarn global add umi
- 1
- 2
- 3
- 4
2.创建项目
// 创建项目mkdir umiAppDemo// 进入项目文件夹cd umiAppDemo// 创建页面umi g page index// 启动项目umi dev
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
3.打包部署
// build打包,会创建一个dist文件umi build
- 1
- 2
四、基本API
1. dynamic—动态加载组件
使用场景:组件体积太大,不适合直接计入 bundle 中,以免影响首屏加载速度。例如:某组件 HugeA 包含巨大的实现 / 依赖了巨大的三方库,且该组件 HugeA 的使用不在首屏显示范围内,可被单独拆出。这时候我们可以更专注于自己的业务组件开发,而不必关心 code spliting、async module loading 等等技术细节。
import { dynamic } from 'umi';export default dynamic({ loader: async function () { // 这里的注释 webpackChunkName 可以指导 webpack 将该组件 HugeA 以这个名字单独拆出去 const { default: HugeA } = await import( /* webpackChunkName: "external_A" */ './HugeA' ); return HugeA; },});// 使用import React from 'react';import AsyncHugeA from './AsyncHugeA';// 像使用普通组件一样即可// dynamic 为你做:// 1. 异步加载该模块的 bundle// 2. 加载期间 显示 loading(可定制)// 3. 异步组件加载完毕后,显示异步组件export default () => { return <AsyncHugeA />;};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
2. 路由组件
这里路由与基本一样分为链接组件和特定样式组件
2.1 链接组件路由
<div> {/* 点击跳转到指定 /home 路由 */} <Link to="/home">home</Link> {/* 点击跳转到指定 /home 路由,携带参数*/} <Link to="/home?sort=name">home</Link> {/* 点击跳转到指定 /home 路由, 附带 query: { sort: 'name' } 附带 hash: 'the-hash' 附带 state: { fromDashboard: true } */} <Link to={{ pathname: '/home', search: '?sort=name', hash: '#the-hash', state: { fromDashboard: true }, }} > home </Link> {/* 点击跳转到指定 /profile 路由,附带所有当前 location 上的参数*/} <Link to={(location) => { ...location, pathname: '/profile' }} /> {/* 点击跳转到指定 /home 路由,但会替换当前 history stack 中的记录 */} <Link to="/home" replace /> {/* innerRef 允许你获取基础组件(这里应该就是 a 标签或者 null) */} <Link to="/courses" innerRef={(node) => { <a>home</a> }} /> </div>
- 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
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
2.2 特定样式组件
特殊版本的 <Link />
。当指定路由(to=指定路由
)命中时,可以附着特定样式。
<div> {/* 和 Link 等价 */} <NavLink to="/home">home</NavLink> {/* 当前路由为 /home 时,附着 class selected */} <NavLink to="/home" activeClassName="selected"> home </NavLink> {/* 当前路由为 /home 时,附着 style */} <NavLink to="/home" activeStyle={{ fontWeight: 'bold', color: 'red', }} >home</NavLink> {/* 当前路由完全匹配为 /home 时,exact代表强校验路由包含斜杠 */} <NavLink exact to="/home" activeClassName="selected"> home </NavLink> {/* 当前路由为 /home/ 时,strict代表包强校验如果没有斜杠校验不通过*/} <NavLink strict to="/home/" activeClassName="selected"> home </NavLink> {/* 当前路由为 /home,并且 query 包含 name 时,附着 class */} <NavLink to="/home" exact activeClassName="selected" isActive={(match, location) => { if (!match) { return false; } return location.search.includes('name'); }} > Profile </NavLink> </div>
- 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
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
3. history—路由对象
引入umi中的history对象,使用内部配置的方法,可以获取路由信息、路由跳转等操作;
3.1 可用于获取当前路由信息
import { history } from 'umi';// history 栈里的实体个数console.log(history.length);// 当前 history 跳转的 action,有 PUSH、REPLACE 和 POP 三种类型const {action} = history;// location 对象,包含 pathname、search 和 hashconst {pathname,search,hash} = history.location;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
3.2 可用于路由跳转
import { history } from 'umi';// 跳转到指定路由history.push('/home');// 带参数跳转到指定路由history.push('/list?a=b');history.push({ pathname: '/list', query: { a: 'b', },});// 跳转到上一个路由history.goBack();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
3.3 用于路由监听
import { history } from 'umi';const unlisten = history.listen((location, action) => { console.log(location.pathname);});unlisten();
- 1
- 2
- 3
- 4
- 5
- 6
4. Prompt—离开页面时的提示选择
import { Prompt } from 'umi';export default () => { return ( <div> {/* 用户离开页面时提示一个选择 */} <Prompt message="你确定要离开么?" /> {/* 用户要跳转到首页时,提示一个选择 */} <Prompt message={(location) => { return location.pathname !== '/' ? true : `您确定要跳转到首页么?`; }} /> {/* 根据一个状态来确定用户离开页面时是否给一个提示选择 */} <Prompt when={formIsHalfFilledOut} message="您确定半途而废么?" /> </div> );};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
5.withRouter—高阶组件
可以通过 withRouter
获取到 history
、location
、match
对象
import { withRouter } from 'umi';export default withRouter(({ history, location, match }) => { return ( <div>{history.action}-{location.pathname}-{`${match.isExact}`} </div> );});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
6. 内置hooks
6.1 useHistory:获取 history
对象
import { useHistory } from 'umi';const history = useHistory();
- 1
- 2
6.2 useLocation:获取 location
对象
import { useLocation } from 'umi';const location = useLocation();
- 1
- 2
6.3 useParams:获取 params
对象。 params
对象为动态路由(例如:/users/:id
)里的参数键值对
import { useParams } from 'umi';const params = useParams();
- 1
- 2
五、总结
-
umi框架扩展性非常强,支持各种功能扩展和业务需求,不在局限于选择vue框架或是react框架;
-
大量自研,包含微前端、组件打包、文档工具、请求库、hooks 库、数据流等,满足日常项目的周边需求;
-
创建项目快,不用像创建react项目一样需要配置typescript/less/css modules;
-
uni框架很多配置都是约定规则,照约定好的方式开发,就能达到某种效果,中间的过程由框架帮我们完成。这使得灵活性降低,但是规范性增强了;