一、Ant Design Pro新增單個頁面目錄
1、 client -> src -> pages 中新增文件夾,比如 category的list
├── category
└── list
└── _mock.js // 模擬數據(可忽略)
└── model.js // 處理請求的model組件,如果簡單請求,直接寫到 index.jsx中,簡單化。(可忽略)
└── index.jsx // 主要的核心文件
└── service.js // 接口請求合集
└── style.less // category 公共樣式
2、在 client -> config -> conifig.js 中 配置的routes 或者 route.js 中添加路由
{ path: '/category', name: '分類', icon: 'category', routes: [ { path: '/category/list', name: '分類列表列表', component: './category/list' } ] },
index.jsx
import React, { Component } from 'react';
import { PageContainer } from '@ant-design/pro-layout'; // 引入布局組件
import { Card, Table, Select, Form, DatePicker, Button, Pagination } from 'antd'; // 引入ant design ui組件
import { getCategoryList } from '../service'; // 引入請求接口
import moment from 'moment'; // 時間日期組件,時間格式
import styles from '../style.less'; // 引入公共樣式,styles.class
const { Option } = Select; // 下拉框引入 Option
const { RangePicker } = DatePicker; // 時間日期組件引入 RangePicker
const dateFormat = 'YYYY-MM-DD'; // 時間日期格式
// 篩選項變量
const selectData = [
{
label: '所屬渠道',
name: 'channel',
style: {
width: '100px'
},
options: [
{
value: 'website',
name: '站內',
},
{
value: 'email',
name: '郵件',
}
]
},
];
// 創建類組件實例
class categoryList extends Component {
// 獲取 DOM 元素節點,通過設置 ref,這里是表單form的ref
formRef = React.createRef();
constructor(props) {
super(props);
this.state = {
channel: '',
selectSourceData: [],
categoryListSource: [],
}
}
// 數據初始化
componentDidMount() {
// 獲取categoryList數據,注意最好不要和service中函數名重復
this.getCategoryListFn();
// 設置篩選項
this.setState({
selectSourceData: selectData
})
};
// 獲取 categoryList
getCategoryListFn = ( params ) => {
params = params ? params : { chanel: 'website' }; // 設置一個默認值,可隨意自定義
getCategoryList({ ...params }).then(res => { // 可以定義分頁參數
if (res.status == 200 ) {
const { data } = res;
this.setState({
categoryListSource: data.list
})
}
});
}
// 切換篩選項
selectChange = (value, attr) => {
// 雙向綁定
this.setState({
[attr.key]: value
});
// 自定義其他操作
}
// 重置
onReset = () => {
this.formRef.current.resetFields();
// 重置初始化
this.setState({
selectSourceData: selectData
})
};
// 搜索提交,請求list,更新table
onFinish = (values) => {
this.getStatDataFn({
channel: values.channel || '',
})
}
// render
render() {
const columns = [
{
title: '推送時間',
dataIndex: 'push_time',
key: 'push_time',
align: 'center',
width: 150,
},
{
title: '事件名稱',
dataIndex: 'event_name',
key: 'event_name',
align: 'center',
width: 150,
},
];
const { loading } = this.props;
const { dateRange, selectSourceData, categoryListSource} = this.state;
return (
<PageContainer>
<Card
className={styles.tabsCard}
>
<Form
layout="inline"
ref={this.formRef}
name="searchObj"
className={styles.formBox}
initialValues={{
channel: '',
dateRange: [],
}}
onFinish={this.onFinish}
onReset={this.onReset}
>
{selectSourceData.map(item => (
<Form.Item
name={item.name}
label={item.label}
key={item.name}
className={styles.formItem}
>
<Select
value={item.name}
style={item.style}
placeholder="請選擇"
disabled={item.disabled}
onChange={this.selectChange}
>
{item.options.map((val, index) => (
<Option key={index} disabled={val.disabled} type={item.name} value={val.value}>{val.name}</Option>
))}
</Select>
</Form.Item>
))}
<Form.Item
key='dateRange'
name="dateRange"
className={styles.formItem}
>
<RangePicker
value={dateRange.length ? [moment(dateRange[0], dateFormat), moment(dateRange[1], dateFormat)] : null} // 重置設置
type="dateRange"
placeholder={['開始時間', '結束時間']}
format={dateFormat}
onChange={(value, dateString) => {
this.setState({
dateRange: dateString
})
}}
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">搜索</Button>
</Form.Item>
<Form.Item>
<Button type="default" htmlType="reset">重置</Button>
</Form.Item>
</Form>
<Table
dataSource={categoryListSource}
bordered={true}
scroll={{ x: 2400 }} // 超出滾動,最大寬度
columns={columns}
rowKey={(record, index) => index}
// pagination={pagination}
// pagination={false}
loading={loading}
// onChange={this.handleTableChange}
/>
</Card>
</PageContainer>
)
}
}
service.js
// 封裝axios,攔截器interceptors import request from '@/utils/request'; // 獲取分類列表 export async function getCategoryList(params) { return request('/admin/report/get-category-list', { method: 'POST', data: params, }); }
二、編譯可能出現警告:
There are multiple modules with names that only differ in casing. This can lead to unexpected behavior when compiling on a filesystem with other case-semantic. Use equal casing. Compare these module identifiers
1、新增文件夾名注意都要小寫,如果多個單詞,用橫杠 — 隔開
2、import 引入的文件注意文件名的大小寫: impor request form '../utils/request.js'
Each child in a list should have a unique "key" prop,Check this render methods of 'Body'
1、如果是table組件,官方給 Table 組件提供了一個 rowKey 屬性,用於給表格的每一行設定一個 key 值
<Table dataSource={this.state.tableDataSource} rowKey={(record, index) => index} // 或者 record.id,index好像啟用了,最好用唯一字段或者拼接字段 > </Table>
2、如果是 map() 循環,遍歷的時候也必須給 key 值
{list.map((item, index) => {
<p key={index}>{{item}}</p>
})
}
Missing message: "menu.分類管理.分類列表" for locale: "zh-CN", using default message as fallback
這是菜單翻譯缺少,請求的菜單需要同步更新
找到 client -> src -> locales -> zh-CN -> menu.js
'menu.分類管理.分類列表': '分類列表',
三、本地開發 menu 導航欄無法加載問題 (https://github.com/ant-design/ant-design-pro/issues/7530)
1、找到 client -> defaultSettings.js, 里面 menus 先注釋掉
2、找到 client -> src -> layouts -> Basiclayout.jsx,找到里面 ProLayout 標簽,在 menuDataRender 屬性配置上面加上配置 menu={{ loading }}
四、componentDidmount 獲取父組件 this.props 中異步數據的失效
這個時候,可以使用更新過程中生命周期 componentWillReceiveProps(nextProps) 來獲取異步ajax請求的數據 nextProps
1、在接受父組件改變后的 props 需要重新渲染組件時用到的比較多
2、接受一個參數 nextProps
3、通過對比 nextProps 和 this.props,將 nextProps 的state為當前組件的state,從而重新渲染組件
五、ant design 關於 Datepicker 限制時間范圍和默認時間
1、限制時間范圍
// 使用disbledDate,當前時間到前7天內選擇時間, 關於moment.js參考官網 http://momentjs.cn/ const disabledDate = (current) => { // moment().subtract(7, "days") 表示當前日期往前推移7天 // moment().endOf( "day") 表示當前日期最后的時間23:59:59 return current && (current < moment().subtract(7, "days") || current >= moment().endOf('day') } <RangPicker disabledDate={this.disabledDate}>
2、默認時間
const dateFormat = 'YYYY-MM-DD'; this.state = { // 當前時間到前30天內 dateRange: [moment().subtract(30, 'days'), moment()], } <RangePicker value={dateRange.length ? [moment(dateRange[0], dateFormat), moment(dateRange[1], dateFormat)] : null} type="dateRange" format={dateFormat} disabledDate={this.disabledDate} > </RangePicker>
