Ant Design Pro 單個頁面目錄結構以及一些常見的報錯


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM