antd学习之Calendar,Upload上传,table,RangePicker,Cascader日历,Timeline时间轴,checkbox,modal,TimePicker,TreeSelect,InputNumber
- 官网
Ant Design of React - Ant Design
- 下载
npm install antd
- 样式引入
import "antd/dist/antd.css";
- select
import React, { Component } from "react";
import { Select } from "antd";
import "antd/dist/antd.css";
class App extends Component {constructor(props) {super(props);this.state = {}this.onSelectChange = this.onSelectChange.bind(this);}onSelectChange(value) {console.log("value", value)}render() {const { Option } = Select;return (<SelectonChange={this.onSelectChange}className="bli_Select"showSearch//placeholder="Select SiteId"defaultValue="all"optionFilterProp="children"filterOption={(input, option) =>option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}>{this.props.filterGroup &&this.props.filterGroup.map((group, i) => {return (<Option value={group} key={"group" + i}>{group}</Option>);})}</Select>);}
}
export default App;
-
DatePicker
1.学习网址:DatePicker - Ant Design
2.代码
import React, { Component } from "react";
import { DatePicker } from "antd";
import moment from "moment";
class App extends Component {constructor(props) {super(props);this.onChangeTime = this.onChangeTime.bind(this);}onChangeTime(value, dateString) {console.log("Selected Time: ", value);console.log("Formatted Selected Time: ", dateString);}render() {const { RangePicker } = DatePicker;return (<RangePickershowTime={
{hideDisabledOptions: true,defaultValue: [moment("00:00:00", "HH:mm:ss"),moment("11:59:59", "HH:mm:ss")]}}onChange={this.onChangeTime}format="YYYY-MM-DD HH:mm:ss"/>);}
}
export default App;
3.效果图
DatePicker和MonthPicker设置默认值
<MonthPicker onChange={this.onChangeEndDate} value={moment(this.state.endDate, "YYYY-MM")}/>
4.引入MonthPicker
如下代码引入日历组件中选择月份可能会由于react和reactDom版本原因而失效
<DatePicker onChange={onChange} picker="month" />
所以,需要引入MonthPicker
render下方
const {MonthPicker} = DatePicker
然后
<MonthPicker onChange={this.onChangeStartDate} />
5、清空之后 显示Invalid date
在日期选择框中进行判断
<DatePickerstyle={
{ width: '110px' }}placeholder="开始日期"onChange={this.handleStartDate}value={startDate === undefined ? startDate : moment(startDate, 'YYYY-MM-DD')}format="YYYY-MM-DD"/>~
- Calendar
1.效果图
2.学习网址
日历 Calendar - Ant Design
3.代码
import React, { Component } from 'react';
import { Calendar } from 'antd';
import './App.css';
import 'antd/dist/antd.css';
class App extends Component {render() {return (<Calendar onSelect={this.onSelect}/>);}
}export default App;
- Upload上传
1.学习网站:上传 Upload - Ant Design
2.效果图:
3.代码:
import React, { Component } from 'react';
import {Upload, message, Button, Icon,
} from 'antd';
import './App.css';
import 'antd/dist/antd.css';
const Dragger = Upload.Dragger;//demo2
const props = {name: 'file',multiple: true,//demo2action: '//jsonplaceholder.typicode.com/posts/',headers: {authorization: 'authorization-text',},onChange(info) {if (info.file.status !== 'uploading') {console.log(info.file, info.fileList);}if (info.file.status === 'done') {message.success(`${info.file.name} file uploaded successfully`);} else if (info.file.status === 'error') {message.error(`${info.file.name} file upload failed.`);}//demo2const status = info.file.status;if (status !== 'uploading') {console.log(info.file, info.fileList);}if (status === 'done') {message.success(`${info.file.name} file uploaded successfully.`);} else if (status === 'error') {message.error(`${info.file.name} file upload failed.`);}},
};
class App extends Component {render() {return (<div><div className="uploadbox"><Upload {...props}><Button><Icon type="upload" /> Click to Upload</Button></Upload></div><div className="uploadbox"><Dragger {...props}><p className="ant-upload-drag-icon"><Icon type="inbox" /></p><p className="ant-upload-text">Click or drag file to this area to upload</p><p className="ant-upload-hint">本地文件服务</p></Dragger></div></div>);}
}export default App;
.uploadbox{width: 520px;height: 150px;text-align: center;margin-right: 20px;float: left;
}
3、上传图片代码示例
遇见如下问题:解决办法是,fileList的图片uid不能设置成相同的。因为这个组件循环多少次是根据fileList的长度来遍历,而图片uid相当于遍历组件的key
import './App.css';
import React, { Component } from 'react'
import { Upload } from 'antd';
import ImgCrop from 'antd-img-crop';
import "antd/dist/antd.css";
class App extends Component {constructor(props) {super(props);this.state = {fileList: [{uid: '1',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"first"},{uid: '2',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"second"},{uid: '3',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"third"},{uid: '4',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"forth"},{uid: '5',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"fiveth"},{uid: '6',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"sixth"},{uid: '7',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"seventh"},{uid: '8',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"eighth"},{uid: '9',name: 'image.png',status: 'done',url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',key:"nineth"}],}}onChange = (value) => {console.log("value====",value)this.setState({fileList:value.fileList})// if (newFileList.file.status === 'uploading') {// // setLoading(true);// return;// }// // setLoading(false);// if (newFileList.file.status === 'done') {// // if (newFileList.file.response && newFileList.file.response.code !== 0) {// // message.error('上传文件错误:' + newFileList.file.response.message);// // return;// // }// // console.log("newFileList",newFileList)// }// if(value.file.status === "removed"){// }};onPreview = async file => {let src = file.url;if (!src) {src = await new Promise(resolve => {const reader = new FileReader();reader.readAsDataURL(file.originFileObj);reader.onload = () => resolve(reader.result);});}const image = new Image();image.src = src;const imgWindow = window.open(src);imgWindow.document.write(image.outerHTML);};render() {return (<div className="App"><ImgCrop rotate ><Uploadaction="https://www.mocky.io/v2/5cc8019d300000980a055e76" listType="picture-card" fileList={this.state.fileList}onChange={(value)=>this.onChange(value)} onPreview={this.onPreview}>{this.state.fileList.length!== 9 && '+ Upload'}</Upload><div>此处想要显示key值</div></ImgCrop></div>);}
}export default App;
showUploadList={ { showRemoveIcon: false }} //隐藏删除按钮
- table
1.学习网站:表格 Table - Ant Design
若数据是record内的一个object里的值,类似:node.attributeSets.edges
{
title: <FormattedMessage id="goods.spu.title.name" />,
dataIndex: ['node', 'nameIntl'],
align: 'left',
render: nameIntl => <span>{getText(nameIntl)}</span>,
},
{
title: <FormattedMessage id="goods.spu.title.type" />,
dataIndex: ['node', 'attributeSets', 'edges'],
align: 'left',
render: attributeSets => renderSpuType(attributeSets),
},
2、合并行
const getRowSpans = (arr, key) => {let sameValueLength = 0;const rowSpans = [];for (let i = arr.length - 1; i >= 0; i--) {if (i === 0) {rowSpans[i] = sameValueLength + 1;continue;}if (arr[i][key] === arr[i - 1][key]) {rowSpans[i] = 0;sameValueLength++;} else {console.log(sameValueLength);rowSpans[i] = sameValueLength + 1;sameValueLength = 0;}}return rowSpans;};
const tableData = [...省略]
const rowSpans = getRowSpans(tableData, 'name');
const columns = [{title: '配置项',dataIndex: 'name',render: (value, _, index) => {const obj = {children: value,props: {},};obj.props.rowSpan = rowSpans[index];return obj;},},
]
3、固定表头
<Table...scroll={
{ y: 240 }}/>
四、RangePicker
1.学习网站:日期选择框 DatePicker - Ant Design
- Cascader
1.学习网站:级联选择 Cascader - Ant Design
2.效果图如下:
3.代码如下:
import React, { Component } from 'react';
import { Cascader, DatePicker } from 'antd';
import './App.css';
import 'antd/dist/antd.css';
const addressdData = [{value: 'zhejiang',label: 'Zhejiang',children: [{value: 'hangzhou',label: 'Hangzhou',children: [{value: 'xihu',label: 'West Lake',}],}],
}, {value: 'jiangsu',label: 'Jiangsu',children: [{value: 'nanjing',label: 'Nanjing',children: [{value: 'zhonghuamen',label: 'Zhong Hua Men',}],}],
}];
function onChange(date, dateString) {console.log(date, dateString);
}
const { RangePicker } = DatePicker;
class App extends Component {render() {return (<div><Cascader style={
{ width: '100%',marginBottom:30}} options={addressdData} placeholder="Select Address" onChange={onChange} /><RangePicker style={
{ width: '100%' }} onChange={onChange} /></div>);}
}export default App;
antd的面包屑,progress,Timeline,还有手风琴效果不错,可以应用到自己的项目中,具体使用看教程
- Timeline时间轴
import React, { Component } from 'react';
import { Timeline , Icon} from 'antd';
import './App.css';
import 'antd/dist/antd.css';
import img2 from './2.jpeg'
class App extends Component {render() {return (<Timeline><Timeline.Item color="green">Create a services site 2015-09-01</Timeline.Item><Timeline.Item color="green">Create a services site 2015-09-01</Timeline.Item><Timeline.Item color="red"><p>Solve initial network problems 1</p><p>Solve initial network problems 2</p><p>Solve initial network problems 3 2015-09-01</p></Timeline.Item><Timeline.Item><p>Technical testing 1</p><p>Technical testing 2</p><p>Technical testing 3 2015-09-01</p></Timeline.Item><Timeline.Item dot={<Icon type="clock-circle-o" style={
{ fontSize: '16px' }} />}><p>Technical testing 2015-09-01</p><img src={img2} alt="no img" /></Timeline.Item></Timeline>);}
}export default App;
- checkbox
import React, { Component } from "react";
import { Checkbox } from 'antd';
import "antd/dist/antd.css";
import "./App.css"
const CheckboxGroup = Checkbox.Group;
const plainOptions = ['Apple', 'Pear', 'Orange'];
const defaultCheckedList = ['Apple', 'Orange'];
class App extends Component {constructor(props) {super(props);this.state = {checkedList: defaultCheckedList,indeterminate: true,checkAll: false,};}onChange = checkedList => {this.setState({checkedList,indeterminate: !!checkedList.length && checkedList.length < plainOptions.length,checkAll: checkedList.length === plainOptions.length,});};onCheckAllChange = e => {this.setState({checkedList: e.target.checked ? plainOptions : [],indeterminate: false,checkAll: e.target.checked,});};render() {return (<div><div className="check_all_box"><Checkboxindeterminate={this.state.indeterminate}onChange={this.onCheckAllChange}checked={this.state.checkAll}>Check all</Checkbox></div><CheckboxGroupoptions={plainOptions}value={this.state.checkedList}onChange={this.onChange}className="check_group_box"/></div>);}
}
export default App;
App.css
.check_all_box{margin-left: 5px;}
.ant-checkbox-group-item{display: block!important;}
.check_group_box{margin-left: 30px;}
- modal
import React, { Component } from "react";
import { Modal as AntdModal } from "antd";
import "antd/dist/antd.css";
class App extends Component {constructor(props) {super(props);this.state = {}}error = () => {AntdModal.info({title: "Incomplete Fields",content: "Please complete all required fields.",centered: true});};handleNext = () => {if(...){this.error();return;}}render() {return (<div onClick={this.handleNext}>123</div>);}
}
export default App;
-
Collapse
import React, { Component } from "react";
import { Collapse } from 'antd';
import "antd/dist/antd.css";
import "./App.css"
class App extends Component {constructor(props) {super(props);this.state = {}}render() {const { Panel } = Collapse;const text = `A dog is a type of domesticated animal.Known for its loyalty and faithfulness,it can be found as a welcome guest in many households across the world.`;return (<Collapsebordered={true}defaultActiveKey={['1', '2', '3']}ghostexpandIconPosition={'right'}><Panel header="" key="1" className="collapse_box"><p>{text}</p></Panel><Panel header="" key="2" className="collapse_box"><p>{text}</p></Panel><Panel header="" key="3"className="collapse_box"><p>{text}</p></Panel></Collapse>);}
}
export default App;
.collapse_box{border-radius: .28571429rem;margin: 50px 50px!important;border: 1px solid rgba(34,36,38,.15);box-shadow: 0 1px 2px 0 rgba(34,36,38,.15);}
-
Steps
两种方法
方法一:
import React, { Component } from "react";
import './App.css';
import { Steps } from "antd";
import "antd/dist/antd.css";
const Step = Steps.Step;
const steps = [{title: '第一步',description: '描述一'
}, {title: '第二步',description: '描述二'
}, {title: '第三步',description: '描述三'
}].map((s, i) => <Step key={i} title={s.title} description={s.description} />);
class App extends Component {render() {return (<div className="App"><Steps current={1}>{steps}</Steps></div>);}
}
export default App;
方法二:
import React, { Component } from "react";
import './App.css';
import { Steps } from "antd";
import "antd/dist/antd.css";
class App extends Component {render() {return (<div className="App"><Steps current={1}><Steps.Step title="第一步" description="描述一"></Steps.Step><Steps.Step title="第二步" description="描述二"></Steps.Step><Steps.Step title="第三步" description="描述三"></Steps.Step></Steps></div>);}
}
export default App;
实际项目中使用
import React, { Component } from "react";
import StepOne from "./stepOne";
import StepTwo from "./stepTwo";
import StepThree from "./stepThree";
import { Steps, Button } from "antd";
import "antd/dist/antd.css";
function getSteps() {return ["step one","step two","step three"];
}
class App extends Component {state = {activeStep: 0};getStepContent(stepIndex) {switch (stepIndex) {case 0:return <StepOne />;case 1:return <StepTwo />;case 2:return <StepThree />;default:return "Unknown stepIndex";}}handleNext = () => {if (this.state.state === 2) {this.setState({ activeStep: 0 })} else {this.setState({ activeStep: this.state.activeStep + 1 })}};handleBack = () => {this.setState({ activeStep: this.state.activeStep - 1 })};render() {const steps = getSteps();const { activeStep } = this.state;return (<div style={
{ paddingTop: 70 }}><Steps size="small" current={activeStep}>{steps.map(label => (<Steps.Step key={label} title={label}></Steps.Step>))}</Steps><div>{this.getStepContent(activeStep)}{activeStep > 0 && activeStep <= 2 ?<Buttondisabled={activeStep === 0}onClick={this.handleBack}>Back</Button> : null}<Buttonvariant="contained"color="primary"onClick={this.handleNext}>{activeStep === 2? "Finish": "Next"}</Button></div></div>);}
}
export default App;
stepOne;stepTwo;stepThree这三个页面这里就不展示了,省略
- TimePicker
注意:回显的时间需要用moment包裹:moment(时间值, 'HH:mm:ss');
useEffect(() => {
newTableData[7]['value'].time = moment(data?.d0WithdrawStartTime, 'HH:mm:ss');
},[])function onChangeTime(e, key) {
}<TimePickervalue={text.time}onChange={(e) => onChangeTime(e, record.key)}format={'HH:mm:ss'}placeholder="选择时间"disabled={record.disabled}
/>
<TimePicker.RangePickervalue={[text?.time[0] ? moment(text.time[0], 'HH:mm') : undefined,text?.time[1] ? moment(text.time[1], 'HH:mm') : undefined,]}format={'HH:mm'}onChange={(e) => onChangeTime(e, record.key)}placeholder={["选择时间", "选择时间"]}/>
-
TreeSelect
<TreeSelectdisabled={JSON.stringify(props.values) !== '{}'}showSearch //显示搜索框treeNodeFilterProp="title" //输入项过滤对应的 treeNode 属性, value或者title.官网解释说,输入项过滤对应的 treeNode 属性,默认是value,style={
{ width: '100%' }}value={value}dropdownStyle={
{ maxHeight: 400, overflow: 'auto' }}placeholder="点击选择上级服务商"allowCleartreeData={props?.agentTree}fieldNames={
{label: 'agentName',key: 'agentCode',value: 'agentCode',children: 'childList',}}treeDefaultExpandAll></TreeSelect>
- InputNumber
//截取部分函数//限制输入框只能输入整数const onlyIntegers = (value) => {return value.replace(/^(0+)|[^\d]/g, '');};//限制输入框只能输入两位小数const limitDecimals = (value) => {return value.replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');};//截图部分return内的代码<InputNumberkey={record.key}min={minDefaultValue}max={maxDefaultValue}value={text}onChange={(e) => onChange(e, record.key)}step={maxDefaultValue == 9999 ? 1 : 0.01}stringModeformatter={maxDefaultValue == 1 ? limitDecimals : onlyIntegers}parser={maxDefaultValue == 1 ? limitDecimals : onlyIntegers}/>