一、项目的目录结构
├── config # umi 配置,包含路由,构建等配置
├── docker # 部署
├── functions #
├── mock # 本地模拟数据
├── public
│ └── favicon.png # Favicon
├── scripts #
├── src
│ ├── assets # 本地静态资源
│ ├── components # 业务通用组件
│ ├── e2e # 集成测试用例
│ ├── layouts # 通用布局,整个网站的共用导航栏,页脚和主体部分; 权限、token获取
│ ├── models # 全局 dva model,换言之是redux(interface、数据交互) (interface、数据交互)
│ ├── pages # 业务页面入口和常用模板
│ ├── services # 后台接口服务请求(get,post)
│ ├── utils # 工具库(放一些公用方法)
--创建src下创建util目录,并且创建request.js文件·「放状态码」,输入如下内容:(用于异步请求数据)
│ ├── g2.js # 可视化图形配置
│ ├── theme.js # 主题配置
│ ├── locales # 国际化资源
│ ├── global.less # 全局样式
│ └── global.ts # 全局 JS
├── tests # 测试工具
├── README.md
└── package.json
.editorconfig 编辑器配置文件
.eslintrc ESLint配置文件
.gitignore Git忽略文件
.roadhogrc.mock.js Mock配置文件
.webpackrc 自定义的webpack配置文件,JSON格式,如果需要 JS 格式,可修改为 .webpackrc.js
链接:https://www.jianshu.com/p/c7b3b9c98d04
二、主要目录和文件介绍
1、config 目录
├── config # umi 配置,包含路由,构建等配置
│ ├── config # 配置文件:包含路由、样式、proxy等
│ ├── defaultSettings # 默认设置:包括标题title、navTheme等
│ ├── plugin.config # webpack的Plugin配置
│ ├── router.config # 路由配置
│ ├── themePluginConfig # 风格主题的配置
2、src 目录
1、src/components组件目录
(1)src/components/Authorized组件
授权组件,路由权限的管理。
关系:
index.jsx -> Authorized(内容权限管理) -> CheckPermissions
-> renderAuthorize(内容渲染)
-> Secured(判断是否拥有权限访问此 view 权限) -> CheckPermissions
-> CheckPermissions(通用权限检查方法) -> PromiseRender(promise渲染)
(2)src/components/GlobalHeader组件
基础布局的头部,包含搜索、用户头像、语言切换。
├── src/components
├── ...
├── GlobalHeader # 基础布局的头部
│ ├── AvatarDropdown # 用户头像下拉菜单
│ ├── NoticeIconView # 通知图标和通知消息视图
│ ├── plugin.config # webpack的Plugin配置
│ ├── RightContent # 基础布局的头部核心:包含搜索、头像、语言选择
(3)src/components/… 其他组件
HeaderDropdown:头部下拉菜单,用于用户头像、搜索等。
HeaderSearch:头部搜索组件。
NoticeIcon:头部通知组件。
PageLoading:加载组件。
SelectLang:语言切换组件。
2、src/layouts布局
(1)src/layouts/BasicLayout布局
基础默认布局,菜单、顶部、内容、页脚。包含logo、菜单、面包屑等。
ant-design-pro的布局:
(2)src/layouts/SecurityLayout布局
安全布局,负责验证是否登录和登录后跳转加载,我们可以在这里写自己的登录认证规则。
(3)src/layouts/… 其他布局
UserLayout: 用户布局,用于登录页。
BlankLayout: 空白布局,用于打印页面等不需要布局的页面。
3、src/locales
国际化资源语言,包含四种语言:简体中文、繁体中文、英语、葡萄牙语
如果使用国际化请注意它对诸如:菜单、消息提示等影响。如果你是国内用户,那么你可以忽略它。
4、src/models
全局 dva model
1、在 Ant Design Pro 中,一个完整的前端 UI 交互到服务端处理流程是这样的:
1.UI 组件交互操作;
2.调用 model 的 effect;
3.调用统一管理的 service 请求函数;
4.使用封装的 request.ts 发送请求;
5.获取服务端返回;
6.然后调用 reducer 改变 state;
7.更新 model。
2、dva是什么?请看这里:dva.js
它里面的文件内容如下即可:
// model
{
namespace: String, // 命名空间
state: Object, // 状态
reducer: Object, // 同步更新 state
effects: Object, // 副作用:处理异步逻辑
subscriptions: Object // 订阅数据源
}
这些文件被引用在src/pages/.umi/dva中
dvajs:
https://dvajs.com
https://dvajs.com/guide/concepts.html#models
https://dvajs.com/api/#app-start-selector
3、Model 是 dva 最重要的部分,可以理解为 redux、react-redux、redux-saga 的封装。
通常项目中一个模块对应一个 model,一个基本的 model 如下:
import { fetchUsers } from '../services/user';
export default {
namespace: 'user',
state: {
list: [],
},
reducers: {
save(state, action) {
return {
...state,
list: action.data,
};
},
},
effects: {
*fetch(action, { put, call }) {
const users = yield put(fetchUsers, action.data);
yield put({ type: 'save', data: users });
},
},
subscriptions: {
setup({ dispatch, history }) {
return history.listen(({ pathname }) => {
if (pathname === '/user') {
dispatch({ type: 'fetch' });
}
});
},
},
}
另一个例子:
import * as services from '../services';
{
namespace: 'system', //models命名空间,需全局唯一
state: {
dataList: []
}, //models存储的数据store
reducers: {
save(state, { payload }) { //更新store,用新数据合并state的旧数据
return { ...state, ...payload };
}
},
effects: {
* testFunc({ payload: params }, { call, put, select }) { //dispatch请求的方法
const { dataList } = yield select(state => state.system); //获取models中的state
const { data } = yield call(services.testFunc, params); //call,请求services里面的接口以及传参,可继续往后面加参数,跟JavaScript的call一样
if (data && data.code == 0) {
const data_ = data.data.content;
yield put({ //put,必须发出action save,此action被reducer监听,从而达到更新state数据的目的
type: 'save',
payload: {
dataList: data_ || []
}
});
return data_; //返回response,可选
}
},
},
subscriptions: { //订阅,在app.start()即启动项目时被执行
setup({ dispatch, history }) {
return history.listen(({ pathname, query }) => {
// 进入 '/manager/system' 路由,会发起一个名叫 'save' 的 effect
if (pathname === '/manager/system') {
//do sth... dispatch({ type: 'save', payload: query });
}
})
}
}
}
namespace
是该 model 的命名空间,同时也是全局state
上的一个属性,只能是字符串,不支持使用.
创建多层命名空间。state
是状态的初始值。该 Model 当前的状态。数据保存在这里,直接决定了视图层的输出reducer
类似于 redux 中的 reducer,它是一个纯函数,用于处理同步操作,是唯一可以修改state
的地方,由action
触发,它有state
和action
两个参数。effects
用于处理异步操作,不能直接修改state
,由action
触发,也可触发action
。它只能是generator
函数,并且有action
和effects
两个参数。第二个参数effects
包含put
、call
和select
三个字段,put
用于触发action
,call
用于调用异步处理逻辑,select
用于从state
中获取数据。subscriptions
用于订阅某些数据源,并根据情况 dispatch 某些 action,格式为({ dispatch, history }, done) => unlistenFunction
。
如上的一个 model,监听路由变化,当进入 /user
页面时,执行 effects
中的 fetch
,以从服务端获取用户列表,然后 fetch
中触发 reducers
中的 save
将从服务端获取到的数据保存到 state
中。
注意,在 model 中触发这个 model 中的
action
时不需要写命名空间,比如在fetch
中触发save
时是{ type: 'save' }
。而在组件中触发action
时就需要带上命名空间了,比如在某个组件中触发fetch
时,应该是{ type: 'user/fetch' }
4、dva: connect
当写完 model 和组件后,需要将 model 和组件连接起来。dva 提供了 connect 方法,其实它就是 react-redux 的 connect。用法如下:
import React from 'react';
import { connect } from 'dva';
const User = ({ dispatch, user }) => {
return (
<div></div>
)
}
export default connect(({ user }) => {
return user;
})(User);
connect 后的组件除了可以获取到 dispatch 和 state,还可以获取到 location 和 history
链接:https://www.jianshu.com/p/c7b3b9c98d04
5、src/pages
业务页面和常用模板
1、src/pages/document.ejs 默认html模板,umi 约定如果这个文件存在,会作为默认模板,内容上需要保证有
<div id="root"></div>
,模板里可通过 context 来获取到 umi 提供的变量。
2、user user业务逻辑内容,里面包含login登录模块,如果你需要更换登录页,请在这里处理。
6、src/services
服务请求层,在 Ant Design Pro 中,后台接口服务需要写在services文件下
例如登录的请求:
import request from '@/utils/request';
export async function fakeAccountLogin(params) {
return request('/api/login/account', {
method: 'POST',
data: params,
});
}
export async function getFakeCaptcha(mobile) {
return request(`/api/login/captcha?mobile=${mobile}`);
}
链接:https://www.jianshu.com/p/311e3e41688d