一、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>