【共享單車】—— React後臺管理系統開發手記:AntD Form基礎元件
阿新 • • 發佈:2019-01-09
前言:以下內容基於React全家桶+AntD實戰課程的學習實踐過程記錄。最終成果github地址:https://github.com/66Web/react-antd-manager,歡迎star。
一、使用Form元件開發登入頁面
- pages->form->login.js:對應路由/admin/form/login
import React from 'react' import {Card, Form, Input, Button, message, Icon, Checkbox} from 'antd' const FormItem = Form.Item class FormLogin extends React.Component{ handleSubmit = () => { let userInfo = this.props.form.getFieldsValue(); this.props.form.validateFields((err, values) => { if(!err){ message.success(`${userInfo.userName} 恭喜你,您通過本次表單元件學習,當前密碼為:${userInfo.userPwd}`) } }) } render(){ const { getFieldDecorator } = this.props.form; return ( <div> <Card title="登入行內表單"> <Form layout="inline"> <FormItem> <Input placeholder="請輸入使用者名稱"/> </FormItem> <FormItem> <Input placeholder="請輸入密碼"/> </FormItem> <FormItem> <Button type="primary">登入</Button> </FormItem> </Form> </Card> <Card title="登入水平表單" style={{marginTop:10}}> <Form layout="horizontal" style={{width:300}}> <FormItem> { getFieldDecorator('userName', { initialValue:'Elena', rules:[ { required: true, message:'使用者名稱不能為空' }, { min:5, max:10, message: '長度不在範圍內' }, { pattern: new RegExp('^\\w+$','g'), message: '使用者名稱必須為字母或數字' } ] })( <Input prefix={<Icon type="user"/>} placeholder="請輸入使用者名稱"/> ) } </FormItem> <FormItem> { getFieldDecorator('userPwd', { initialValue:'123456', rules:[ { required: true, message:'密碼不能為空' }, { min:6, max:8, message: '長度不在範圍內' } ] })( <Input prefix={<Icon type="lock"/>} type="password" placeholder="請輸入密碼"/> ) } </FormItem> <FormItem> { getFieldDecorator('remember', { valuePropName: 'checked', initialValue: true, })( <Checkbox>記住密碼</Checkbox> ) } <a href="#" style={{float:'right'}}>忘記密碼</a> </FormItem> <FormItem> <Button type="primary" onClick={this.handleSubmit}>登入</Button> </FormItem> </Form> </Card> </div> ) } } export default Form.create()(FormLogin);
- Form元件
- layout屬性:表示表單佈局 -- inline行內表單/horizontal水平表單
- getFieldDecorator屬性:幫助進行初始化值,獲取資料
- getFieldDecorator(‘表單裡的一些物件’,定義的規則和值)(元件)
{ getFieldDecorator('userName', { initialValue:'Elena', rules:[ { required: true, message:'使用者名稱不能為空' }, { min:5, max:10, message: '長度不在範圍內' }, { pattern: new RegExp('^\\w+$','g'), message: '使用者名稱必須為字母或數字' } ] })( <Input prefix={<Icon type="user"/>} placeholder="請輸入使用者名稱"/> ) }
需要在元件最下方新增 ↓:(經過
Form.create
包裝的元件將會自帶this.props.form
屬性)export default Form.create()(FormLogin);
-
prefix屬性:加字首,使用Icon元件新增小圖示
<Input prefix={<Icon type="user"/>} placeholder="請輸入使用者名稱"/>
-
指定表單的寬度
style={{width:300}}
- 設定記住密碼框預設選中
{ getFieldDecorator('remember', { valuePropName: 'checked', initialValue: true, })( <Checkbox>記住密碼</Checkbox> ) }
- options.rules校驗規則
- required:是否必選
- min : 最小長度
- max : 最大長度
- len : 欄位長度
- partten : 正則表示式
- type: 內建校驗型別 型別選項
二、使用Form元件開發註冊頁面
- pages->form->register.js:對應路由/admin/form/reg
import React from 'react' import moment from 'moment' import {Card,Form,Input,Button,Checkbox,Radio,InputNumber,Select,Switch,DatePicker,TimePicker,Upload,Icon,message} from 'antd' const FormItem = Form.Item const RadioGroup = Radio.Group const Option = Select.Option; const TextArea = Input.TextArea class FormRegister extends React.Component { state = { loading: false, }; handleSubmit = () => { let userInfo = this.props.form.getFieldsValue(); console.log(JSON.stringify(userInfo)) message.success(`${userInfo.userName} 恭喜你,您通過本次表單元件學習,當前密碼為:${userInfo.userPwd}`) } handleResetInfo = () => { this.props.form.resetFields(); } //模擬上傳jpg -- 直接從官網複製過來即可 getBase64 = (img, callback) => { const reader = new FileReader(); reader.addEventListener('load', () => callback(reader.result)); reader.readAsDataURL(img); } handleChange = (info) => { if (info.file.status === 'uploading') { this.setState({ loading: true }); return; } if (info.file.status === 'done') { // Get this url from response in real world. this.getBase64(info.file.originFileObj, imageUrl => this.setState({ userImg: imageUrl, loading: false, })); } } render(){ const { getFieldDecorator } = this.props.form; const formItemLayout = { labelCol: { xs: 24, sm: 4 }, wrapperCol: { xs: 24, sm: 12 } } const offsetLayout = { wrapperCol: { xs: 24, sm: { span:12, offset:4 } } } const rowObject = { minRows: 4, maxRows: 6 } return ( <div> <Card title="登錄檔單"> <Form layout="horizontal"> <FormItem label="使用者名稱" {...formItemLayout}> { getFieldDecorator('userName', { initialValue:'Elena', rules:[ { required: true, message:'使用者名稱不能為空' } ] })( <Input placeholder="請輸入使用者名稱"/> ) } </FormItem> <FormItem label="密碼" {...formItemLayout}> { getFieldDecorator('userPwd', { initialValue:'123456', rules:[ { required: true, message:'密碼不能為空' } ] })( <Input type="password" placeholder="請輸入密碼"/> ) } </FormItem> <FormItem label="性別" {...formItemLayout}> { getFieldDecorator('sex', { initialValue:'1' })( <RadioGroup> <Radio value="1">女</Radio> <Radio value="2">男</Radio> </RadioGroup> ) } </FormItem> <FormItem label="年齡" {...formItemLayout}> { getFieldDecorator('age', { initialValue:'18' })( <InputNumber /> ) } </FormItem> <FormItem label="當前狀態" {...formItemLayout}> { getFieldDecorator('state', { initialValue:'1' })( <Select> <Option value="1">鹹魚一條</Option> <Option value="2">人民公僕</Option> <Option value="3">浙傳才女一枚</Option> <Option value="4">科技公司FE</Option> <Option value="5">創業者</Option> </Select> ) } </FormItem> <FormItem label="愛好" {...formItemLayout}> { getFieldDecorator('state', { initialValue:['1','3','5'] })( <Select mode="multiple"> <Option value="1">旅行</Option> <Option value="2">讀書</Option> <Option value="3">剪輯</Option> <Option value="4">拍照</Option> <Option value="5">看電影</Option> </Select> ) } </FormItem> <FormItem label="是否已婚" {...formItemLayout}> { getFieldDecorator('isMarried', { valuePropName: 'checked', initialValue: true })( <Switch /> ) } </FormItem> <FormItem label="生日" {...formItemLayout}> { getFieldDecorator('birthday', { initialValue: moment('2019-1-1 11:14:59') })( <DatePicker showTime format="YYYY-MM-DD HH:mm:ss" /> ) } </FormItem> <FormItem label="聯絡地址" {...formItemLayout}> { getFieldDecorator('address',{ initialValue: '西虹市海淀區桃花公園' })( <TextArea autosize={rowObject} /> ) } </FormItem> <FormItem label="早起時間" {...formItemLayout}> { getFieldDecorator('time')( <TimePicker /> ) } </FormItem> <FormItem label="頭像" {...formItemLayout}> { getFieldDecorator('userImg')( <Upload listType="picture-card" showUploadList={false} action="//jsonplaceholder.typicode.com/posts/" onChange={this.handleChange} > {this.state.userImg?<img src={this.state.userImg}/>:<Icon type="plus"/>} </Upload> ) } </FormItem> <FormItem {...offsetLayout}> { getFieldDecorator('imooc')( <Checkbox>我已閱讀過<a href="#">慕課協議</a></Checkbox> ) } </FormItem> <FormItem {...offsetLayout}> <Button type="primary" onClick={this.handleSubmit}>提交</Button> <Button style={{marginLeft:10}} onClick={this.handleResetInfo}>重置</Button> </FormItem> </Form> </Card> </div> ) } } export default Form.create()(FormRegister);
- Form支援響應式尺寸
//Form元件內嵌的柵格佈局 const formItemLayout = { labelCol: { xs: 24, sm: 4 }, wrapperCol: { xs: 24, sm: 12 } } //偏移佈局 const offsetLayout = { wrapperCol: { xs: 24, sm: { span:12, offset:4 //向右偏移4列 } } }
-
數字框:
<InputNumber/>
-
時間類元件: DatePicker
value
型別為moment
物件,所以在提交伺服器前需要預處理-
安裝moment
yarn add moment --save
-
引用moment
import moment from "moment"; …… <FormItem label="生日" {...formItemLayout}> { getFieldDecorator('birthday', { initialValue: moment('2019-1-1 11:14:59') })( <DatePicker showTime format="YYYY-MM-DD HH:mm:ss" /> ) } </FormItem>
-
獲取表單中Object物件
-
呼叫getFieldsValue方法:獲取一組輸入控制元件的值,如不傳入引數,則獲取全部元件的值
let userInfo = this.props.form.getFieldsValue();
-
重置表單內容:呼叫resetFields方法
this.props.form.resetFields()
-
注意:使用
getFieldsValue、
getFieldValue、
setFieldsValue
等時,需要確保對應的 field 已經用getFieldDecorator
註冊過了 -
其它Api:官網文件
- 上傳檔案類元件:Upload
- action屬性:上傳的伺服器地址
- listType屬性:上傳列表的內建樣式
text/
picture/
picture-card
- showUploadList屬性:是否展示上傳列表內容 {false}↑ 或{true}↓
- onChange屬性:上傳檔案狀態改變的回撥,詳見 onChange
- 使用Upload元件必需的幾個方法:
//模擬上傳jpg -- 直接從官網複製過來即可 getBase64 = (img, callback) => { const reader = new FileReader(); reader.addEventListener('load', () => callback(reader.result)); reader.readAsDataURL(img); } handleChange = (info) => { if (info.file.status === 'uploading') { this.setState({ loading: true }); return; } if (info.file.status === 'done') { // Get this url from response in real world. this.getBase64(info.file.originFileObj, imageUrl => this.setState({ userImg: imageUrl, loading: false, })); } }
注:專案來自慕課網