- 不可改动的数据如果比较多的话应该使用规整对齐的文字类似于表格来显示,这样的话比使用input设置为disabled要好一些。
- 在使用input时,注意增加palceholder和rules的验证会有更加良好的用户体验
- 在componentDidMount获取列表数据时,以及新增页面点击保存按钮时增加loading,避免用户多次操作,增加loading的方式大概有两种:
loading:loading.models.xxx
loading:loading.effects['xxx/xxx']
- 对list中的数据title进行一定的考量,一般的list最好是增加一列序号列,这样的好处是在用户翻页的时候会有非常直观的感受,知道已经翻页了
- 对list中的时间可以进行sorter排序,对状态使用filters筛选
- 对于有list也有detail需要打开侧面抽屉的页面,我们会将数据放在models中,是因为当我们在抽屉中进行修改的时候,models会发生改变,触发list页面更新
就像这样的页面
7.对于model中的数据,通常我们在reducers中会有两个方法,一个是save,一个是update,
save(state, {payload}) {
return {
...state,
...payload,
};
},
update(state,{payload}){
return{
...state,
...payload,
}
}
这样写的话我们只需要在effects当中将特定的数据名称和结构放在payload中,在reducers中将payload解出来return即可。
就像这样:
effects中:
* getGuideState({payload}, {call, put}) {
const response = yield call(basicData.getDictionaryList, payload);
yield put({
type: 'save',
payload: {
guideState: response.data.rows,
},
});
},
reducers中
save(state, {payload}) {
return {
...state,
...payload,
};
},
最开始的时候我犯了一个很蠢的错误就是对于每一个effects,我都在reducers中设置了对应的一个函数。
8.当几个页面是具有一定的流程的时候,这个页面用到了那个页面的数据,此时我们需要注意,首先需要注意的是,一般来说新增和修改都是通一个页面,当我们修改完之后,需要将此页面的model数据置空,否则下次新增的时候将会看到上一次的数据,具体的做法就像这样
yield put({
type:'update',
getAllAboutPrj:{},
})
其次需要注意的是,不能让两个页面的数据在model中对应相同的数据,因为一个页面中数据的变化将会导致model变化,从而触发更新,这样很容易造成许多问题,你会发现你在一个页面中操作的时候,突然报了一个另一个页面的错误,原因就在于他们在model中共用了同一个数据
9.为了防止cannot get xxx of undefined的错误,我们一般使用=进行赋初值
10.后台返回来的状态数据是数字,我们通常需要在数据字典接口中获取他们的key与value,然后通过这样的方法将其显示为其对应的value,就像下面这样:
render:function(v){
const result = guideState.filter((current)=>{
return current.k==v;
})[0]
return (result&&result.val) || ""
},
11.在表格列表中显示数据如果遇到数据比较长的情况,我们可以用省略号来表示超出的部分,并设置悬浮显示全称
render: (record = "") => {
let data = record.replace(/[^\u4e00-\u9fa50-9a-zA-Z]/g, '');
if (data.length > 10) {
data = data.substring(0, 9)
data = data + "......"
}
return (
<Popover
content={record}
autoAdjustOverflow
mouseEnterDelay={0.2}
placement='right'
>
<a>{data}</a>
</Popover>
)
},
12.对于组件,为了确保每个使用的组件都能传递有效的数据,就像下面这样:
component.propTypes = {
searchList: PropTypes.array.isRequired, // searchList应该是一个数组
}
13.在对list页面设置搜索框时,我们需要注意的是,在重置时应该先发一次list的请求,否则搜索之后再重置list就只是刚刚的搜索结果
14.以前当我们需要在path中添加参数,并在另一个页面中获取它时,我们通常是这样做的
const matchEdit = pathToRegexp('/gridInfoManage/areaEdit/:id').exec(location.pathname)
这样做的原因是虽然locatio中有很多方法可以传递给另一个页面,但是这些数据一旦刷新就会被重置,所以我们一般都是采用path。
现在我们可以直接这样获取
const {dispatch, match: {params}, form} = this.props;
在params中就保存有传递过来的参数,这样就不需要我们去匹配
15.当需要从一个页面跳转到另一个页面,并且第一个页面需要在菜单中显示,第二个页面不在菜单中显示的时候我们配置路径的时候,我们可以将不显示的菜单设置成子菜单,运用hideChildrenInMenu: true,来隐藏菜单,这样的话,子菜单的路径的一部分需要与父菜单一致,就像下面这样
{
name: '个人项目',
icon: 'setting',
path: '/PersonalProject',
authority: ['超级管理员','申报者'],
routes: [
{
path: '/PersonalProject/GuideList',
name: '指南列表',
hideChildrenInMenu: true,
routes:[
{
path: '/PersonalProject/GuideList',
name: '指南列表',
component: './PersonalProject/GuideList',
},
{
path: '/PersonalProject/GuideList/ProjectSubmit/:id/:add',
name: '项目申报',
component: './PersonalProject/ProjectSubmit',
},
],
},
{
path: '/PersonalProject/MyProject',
name: '我的项目',
component: './PersonalProject/MyProject',
}
]
},
16.跳转路由时,我们可以使用es6,字符串模版传参,就像下面这样
import router from 'umi/router';
router.push(`/PersonalProject/GuideList/ProjectSubmit/${selectedRows[0].guideId}/1`);
17.如果能够共用service层的函数,我们应该尽量共用,而不单独写
在一个名为personalProject的model当中,我们调用了guideService中的getDetail
import * as guideService from '@/services/eguide';
* getGuide({payload}, {call, put}) {
const response = yield call(guideService.getDetail, payload);
yield put({
type: 'save',
payload: {
detailData: response.data,
},
});
yield put({
type: 'update',
getAllAboutPrj: {},
})
},
export async function getDetail(param) {
return request(createTheURL(Config.API.EGUIDE, 'get'), {
method: 'GET',
body:param,
});
}
18.在使用form实现双向绑定时,如果表单中没有数据,那么在render中打印出从props中解出来的数据,会比在model中打印更高效的解决问题
19.在对表格设置columns时,如果不需要用到props中的数据,那么我们可以将其写在class中,这样会有效的节约内存,因为如果写在render中,每当有数据变化的时候,就会触发render
columns = [
{
title : '商品名',
dataIndex : 'goodsName',
key : 'goodsName',
},
{
title : '商品类型',
dataIndex : 'goodsType',
key : 'goodsType',
}]
<StandardTable columns={this.columns} />
而当表格中数据需要用到props中传递过来的数据时,我们必须将其放在render中,否则的话,我们可能拿不到数据
const columns = [
{
title: '序号',
key: 'index',
dataIndex: 'index',
align: 'left',
render: (text, record, index) => <span>{index + 1}</span>,
width: 80,
},
{
title: '指南状态',
dataIndex: 'state',
key: 'state',
align: 'center',
width: 100,
render: function (v) {
return utils.getAllDictNameById(gDictData,"guideState",v)||"";
},
},
];
<StandardTable columns={columns} />
20.如果我们有这样一个流程,我们在指南列表中选定一个指南,在这个指南下新建申报项目,然后保存,新建的项目就会被保存到项目列表中,如果选中项目列表中的某一项,我们会进入项目的修改页面,其实是和新建申报项目是同一个页面。这样的话就存在一个问题,如果我先进行修改,此时就会打开修改页面,然后我再新增的话,因为修改页面的tab没有被关闭,而新增进入的是同一个页面,所以此时就没有办法触发componentDidMount,而一般来说我们是在componentDidMount中去调用model将修改时的数据变为空,因为tab没有关闭,componentDidMount不被触发,所以这样的方法应该是不可以被使用的,所以我采用了,在每一次要进入新增或者是修改页面的时候,都发一次请求去把项目申报的页面关闭一次。
closeProjectSubmit = ()=>{
const {dispatch} = this.props;
dispatch({
type: 'global/closeCurrentTab',
payload: {
tabName: '项目申报',
},
})
}