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>

 

posted @ 2021-05-17 11:58  浪里小韭菜  阅读(1463)  评论(0编辑  收藏  举报