一、项目初始化
- 创建并进入目录
mkdir umijs cd umujs - 创建umi项目
yarn create @umijs/umi-app npx @umijs/create-umi-app - 安装依赖
yarn - 启动项目
yarn start - 打包,部署发布
yarn build (构建后项目中会多一个dist项目) - 本地验证
yarn global add serve - - 或 - - npm install http-server -g serve ./dist - - 或 - - http-server ./dist - 获取镜像源
yarn config get registry
二、基本了解
2.1.路由配置
.umirc.ts
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
hash:true,
title:'UmiJS标题',
routes: [
{ path: '/', component: '@/pages/index',title:'首页' },
{ path: '/list', redirect:'/user/one' },
{
path:'/user',
component:'@/layouts/index',
wrappers:[
'@/wrappers/auth',
],
routes:[
{ path: '/user/one', component: '@/pages/user2',title:'用户页面2'},
{ path: '/user/two', component: '@/pages/user',title:'用户页面'},
{ component:'@/pages/404'}
]
},
{ component:'@/pages/404'}
],
fastRefresh: {},
});
layouts.index.tsx
import React from 'react';
import { Link, NavLink } from 'umi';
import './index.less';
const Index = (props: any) => {
return (
<div>
<h2>Header</h2>
{}
{}
<NavLink to={'/user/one'}>用户1</NavLink>
<NavLink to={'/user/two'}>用户2</NavLink>
{}
{props.children}
<h2>Footer</h2>
</div>
);
};
export default Index;
pages/index.less
.active {
color: red;
font-size: 33px;
}
pages/index.tsx
import styles from './index.less';
import { DatePicker } from 'antd';
export default function IndexPage(props: any) {
console.log('dnlsbd', props.match.params);
console.log('dnlsbd', props.match.params.id);
return (
<div>
<h1 className={styles.title}>Page index</h1>
<DatePicker />
</div>
);
}
pages/user2.tsx
import React from 'react';
const User = () => {
return <div>User Page2</div>;
};
export default User;
pages/user1.tsx
import React from 'react';
import { Button } from 'antd';
const User = (props: any) => {
return (
<div>
<span>User Page1</span>
<Button
onClick={() => {
props.history.push('/');
}}
>
点我回首页
</Button>
</div>
);
};
export default User;
pages/404.tsx
import React from 'react';
const NotFound = () => {
return (
<div>
<h1>404</h1>
</div>
);
};
export default NotFound;
wrappers/auth.tsx
import { Redirect } from 'umi';
export default (props: any) => {
const isLogin = true;
if (isLogin) {
return <div>{props.children}</div>;
} else {
return <Redirect to="/login" />;
}
};
2.2.Html模板
在node_modules/@umijs/core/lib/Html/document.ejs中,里面是将组件挂载到页面上 由于模板代码在node_modules中,一般提交版本代码时是不会提交node_modules的,所以不要在模板上进行修改
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />
</head>
<body>
<div id="<%= context.config.mountElementId || 'root' %>"></div>
</body>
</html>
新建 src/pages/document.ejs,umi 约定如果这个文件存在,会作为默认模板
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>自定义模板</title>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<h3>自定义模板</h3>
<button class="btn btn-success">bootstrap</button>
<div id="root"></div>
</body>
</html>
2.3.Mock数据
- Mock数据是前后端分离开发的关键步骤,通过跟服务器预先约定好的接口,模拟请求数据和逻辑
- 在mock文件夹下写的js或ts文件都会被认为是mock文件
- 可以引入Mock.js第三方库提升Mock数据能力
mock:false
"start:nomock": "MOCK=none umi dev"
mock/index.ts
import mockjs from 'mockjs'
export default {
'GET /api/index' : {
id: 1,
name: 'Tom',
age: 12
},
'GET /api/person' : {
id: 2,
name: 'LiLi',
age: 21
},
'GET /api/tags' : mockjs.mock({
'list|100':[{name:'@city','value|1-100':50,'type|0-2':1}]
})
}
pages/index.tsx
import styles from './index.less';
import { DatePicker, Button } from 'antd';
import { useEffect } from 'react';
import { history, request } from 'umi';
export default function IndexPage(props: any) {
useEffect(() => {
setTimeout(() => {
history.push('/user/one');
}, 2000);
});
const getData = () => {
request('/api/index').then((res) => {
console.log(res);
});
};
const getData2 = async () => {
const data = await request('/api/person');
console.log(data);
};
const getData3 = async () => {
const data = await request('/api/tags');
console.log(data);
};
return (
<div>
<h1 className={styles.title}>Page index</h1>
<Button onClick={getData3}>点击获取数据</Button>
<DatePicker />
</div>
);
}
2.4.DvaJS
- umi已经给我们提供plugin-dva插件了
- dva的作用就是让我们更方便的使用redux
- 约定式的model文件
src/models下的文件(推荐使用),src/pages/models目录下的文件,src/pages/model.ts文件 会有校验内容是否是有效的dva model
- 1.创建ui组件 src/pages/tags.tsx(记得配置路由)
- 2.创建model src/models/tags.ts
- 3.使用connect将ui组件和model进行连接
.umirc.ts
{path:'/tags',component:'@/pages/tags'},
pages/tags.tsx
import React from 'react';
import { connect } from 'umi';
import { Button } from 'antd';
const Tags = (props) => {
const { dispatch } = props;
const tagslist = props.tags.tagsList.list || [];
const getTagsList = () => {
dispatch({
type: 'tags/fetchTagsList',
payload: null,
});
};
return (
<div>
<h3>Dva的使用</h3>
<Button onClick={getTagsList}>点击获取TagsList</Button>
{tagslist.map((item, index) => {
return <p key={index + item}>{item.name}</p>;
})}
</div>
);
};
export default connect(({ tags }) => ({ tags }))(Tags);
src/models/tags.ts
import {request} from 'umi'
const getTags = () => {
return request('/api/tags')
}
export default{
namespace:'tags',
state:{
tagsList:[]
},
effects:{
*fetchTagsList({payload,callback},{put,call}){
const tagsList = yield call(getTags)
yield put({
type: 'setTagsList',
payload: tagsList
})
}
},
reducers:{
setTagsList(state,action){
console.log("skanbdjad",state)
console.log("skanbdjad",action)
return {...state,tagsList:action.payload}
}
}
}
2.5.运行时配置
运行时配置:约定写在src/app.tsx中
import { history } from 'umi';
let extraRoutes;
export function patchRoutes({ routes }) {
routes.unshift({
path: '/foo',
title: 'foo',
component: require('@/pages/user1').default,
});
extraRoutes.map((item) => {
routes.unshift({
path: item.path,
component: require(`@/pages${item.component}`).default,
});
});
}
export function render(oldRender) {
extraRoutes = [{ path: '/server', component: '/user2' }];
const isLogin = true;
if (!isLogin) {
history.push('/login');
}
oldRender();
}
export function onRouteChange({ location, routes, action, matchedRoutes }) {
console.log(location);
console.log(location.pathname);
console.log('jhbad vsd', matchedRoutes);
console.log('jhbad vsd', matchedRoutes.length);
if (matchedRoutes.length) {
document.title =
'郑州师范 ' + (matchedRoutes[matchedRoutes.length - 1].route.title || '');
}
console.log(routes);
console.log(action);
}
2.6.Umi-UI
- 安装umi-ui的依赖
yarn add @umijs/preset-ui -D - 在项目package.json中配置
linux:“start:umi-ui”: “UMI_UI=1 umi dev” windows:“start:umi-ui”: “set UMI_UI=1 && umi dev” - 运行:yarn start:umi-ui
打开项目后,点击右下角Umi UI的可视化编程根据,解决以下问题 在项目根目录下创建一个.env文件,里面进行以下配置:HOST=0.0.0.0
通过点击引入相关的Umi-Ui的模板或区块,引入区块中的布局,点击添加到项目中,项目中pages下会出现一个LayoutSide组件 需要进行调整,在src下创建一个layouts文件夹,将LayoutSide组件放到layouts下面,并修改.umirc.ts下的路由配置
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{
name: '注册页',
path: '/userregister',
component: './UserRegister',
},
{
name: '模板组件',
title: '数字郑州',
path: '/',
component: '@/layouts/LayoutSide/index',
routes: [
{
name: '空白页面',
path: '/user',
component: '@/pages/User/index',
},
{
name: '首页',
path: '/index',
component: '@/pages/index',
},
],
},
],
fastRefresh: {},
dva: {
immer: true,
hmr: false,
},
locale: {
default: 'zh-CN',
antd: false,
title: false,
baseNavigator: true,
baseSeparator: '-',
}
});
三、项目优化
3.1.配置项
将原来的.umirc.ts文件的内容拆分为以下几个文件,在项目根目录先新建一个config文件夹,下面放四个文件
3.1.1.config.ts
相当于.umirc.ts下的配置
import { defineConfig } from 'umi';
import routes from './routes'
import defaultSetting from './defaultSetting';
import proxy from './proxy'
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
hash:true,
routes,
title:defaultSetting.title,
theme: {
'@primary-color': defaultSetting.PrimaryColor,
},
fastRefresh: {},
targets:{
ie:11
},
proxy:proxy['dev'],
locale:{
default:'zh-CN',
antd:false,
title:false,
baseNavigator:true,
baseSeparator:'-',
},
dva:{
immer:true,
hmr:false,
}
});
3.1.2.defaultSetting.ts
一些默认配置
export default {
PrimaryColor: '#1DA57A',
title:'UmiJS标题',
}
3.1.3.proxy.ts
代理配置
export default [
dev:{
'/api': {
'target': 'http://jsonplaceholder.typicode.com/',
'changeOrigin': true,
'pathRewrite': { '^/api' : '' },
},
},
test:{
'/api': {
'target': 'http://jsonplaceholder.typicode.com/',
'changeOrigin': true,
'pathRewrite': { '^/api' : '' },
},
}
]
3.1.4.routes.ts
路由配置
export default [
[
{
path: '/',
component: '@/layouts/index',
title:'首页',
routes:[
{path:'/',component:'@/pages/index'},
{
path:'/user',
wrappers:[
'@/wrappers/auth',
],
routes:[
{ path: '/user/one', component: '@/pages/user1',title:'用户页面1'},
{ path: '/user/two', component: '@/pages/user2',title:'用户页面2'},
{ component:'@/pages/404'}
]
},
{path:'/tags',component:'@/pages/tags'},
{path:'/login',component:'@/pages/login'},
]
},
{ component:'@/pages/404'}
],
]
3.1.5.utils/request.ts
对request进行封装,可以做一些拦截器,方便在services中使用
import request from 'umi-request'
import {message} from 'antd'
request.interceptors.request.use((url, options) => {
return {
url: `${url}`,
options: { ...options, interceptors: true, headers: {Hello: 'hello'} },
};
});
request.interceptors.response.use(response => {
if(response.status > 400){
const codeMaps = {
404:'未找到资源。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
message.error(codeMaps[response.status]);
}
return response;
});
export default request;
3.1.6.services/tags.ts
在src下创建目录,组件叫什么名字,服务就叫什么名字,将对后端或者models中的请求分离出来
import request from "../utils/request"
export const getTags = () => {
return request('/api/tags')
}
3.2.目录结构
public:一些静态资源,打包时原样复制出去 src/.umi:缓存,每次运行会重新生成,不会进版本库 src/assets:本地静态资源 src/components:公共组件 src/pages/页面组件/components:页面相关的组件 src/services:对后端数据的请求 src/utils:工具类
四、Antd Pro
4.1.创建Antd Pro项目
创建Antd Pro项目(基于umi配置的)
查看yarn的目录
查看全局目录
清缓存
创建Antd Pro项目报错
- yarn config set global-folder “D:\Develop\yarnConfig\yarn_global”
yarn config set cache-folder “D:\Develop\yarnConfig\yarn_cache”
|