ant design v4筆記
前言
最近在使用ant design pro的時候,遇到很多問題,也花費了不少時間,為了防止后續(xù)遺忘,特意記錄一下,也算是幫大家踩坑了。
使用哪個版本
目前最新的是ant design pro v4的版本,但是網(wǎng)上大部分的教程還是v3甚至還要早的,v4和v3相比還是很多地方不一樣的,大部分實例已經(jīng)變成react hook的形式,也就是函數(shù)組件的形式,在v3的時候大多數(shù)還是使用的class。
所以如果是新手學習起步的,建議直接使用v4,學最好學最新的東西,如果是在修改老的項目,優(yōu)先選用當前的版本的代碼,因為改起來還是挺麻煩的,親身經(jīng)歷。
子組件修改父組件的state
目前有兩種情況:
1.使用class的有狀態(tài)組件進行傳值(class那種)
2.使用react hook的函數(shù)組件進行傳值(function的那種)
下面一一展開
首先是 class 形式函數(shù)組件,
import?React?from?"react";
import?{Input}?from?"antd";
export?default?class?Parent?extends?React.Component{
??constructor(props)?{
????super(props);
????this.state?={value:""}
??}
??handleChange?=?(newValue)?=>{
????console.log("父組件獲取新值",newValue);
????this.setState({
??????value:newValue
????});
??}
??render()?{
????return? ;
??}
}
class?MyInput?extends?React.Component{
??handleChange?=(event)=>{
????//?關鍵部分這里的this.props會調(diào)用父組件的方法,進而修改父類的state
????this.props.onChange(event.target.value)
??}
??render()?{
????return?
??}
}
這個例子是在父組件中引入一個包含Input的子組件,子組件的Input組件值發(fā)生改變的時候父組件的也受影響發(fā)生改變。
因為setState是異步的所以在使用的時候,尤其涉及到count計算之類的時候,最好使用下面的形式
???this.setState((preState)=>{
??????return({count:preState.count+1})
????});
???//?preState是歷史的狀態(tài)
同樣的功能使用函數(shù)組件的形式實現(xiàn)
import?{useState}?from?"react"
import?{Input}?from?"antd";
export?default?function?Parent()?{
??// useState是React Hook中的?它的參數(shù)含義如下
??//?第一個值;value 相當于class里面的this.state={value:""}
??//?第二個值:一般約定是setValue這樣的形式,它的作用相當于
??//?this.setState({value:"新的值"})
??const?[value,setValue]?=?useState()
??function?handleChange(newValue){
????console.log("父組件獲取新值",newValue);
????setValue(newValue)
??}
??return?value={value}?onChange?={handleChange}?/>
}
function?MyInput(props){
??function?handleChange(event)?{
????props.onChange(event.target.value)
??}
??return?value={props.value}?onChange={handleChange}/>
}
坑人的Form
從v3升級到v4最坑的就是Form,因為我的項目使用的class 的形式所以,這里沒有使用React Hook的形式去寫,但是官網(wǎng)上v4使用的基本上都是函數(shù)組件的形式,在v3中使用Form的時候,需要使用Form.Create包裹下組件才能使用一些值,但是在V4中是不能使用Form.Create的,所以在這期間我調(diào)查了好久,最后算是解決了,我用的例子就是官網(wǎng)那個可編輯表格,參考v3和官網(wǎng)的遷移指南最后修改完成
/*eslint-disable?*/
import?{Form,?Input,?InputNumber,?Popconfirm,?Table}?from?'antd';
import?React?from?"react";
import?{FormInstance}?from?"antd/es/form";
const?originData:?any?=?[];
for?(let?i?=?0;?i?100;?i+=1)?{
??originData.push({
????key:?i.toString(),
????name:?`Edrward?${i}`,
????age:?32,
????address:?`London?Park?no.?${i}`,
??});
}
class?EditableCell?extends?React.Component<any,?any>?{
??getInput?=?()?=>?{
????if?(this.props.inputType?===?'number')?{
??????return? ;
????}
????return?;
??};
??render()?{
????const?{
??????editing,
??????dataIndex,
??????title,
??????inputType,
??????record,
??????index,
??????children,
??????...restProps
????}?=?this.props
????return?(
??????
????????{editing???(
??????????//?這個地方不用再使用getFieldDecorator(這破玩意至今拼不對)
??????????//?這個name寫了之后?初始值就要在Form上設置了?initialValues
??????????0}}?rules={[{
????????????required:?true,
????????????message:?`Please?Input?${title}!`,
??????????}]}>
????????????{this.getInput()}
??????????
????????)?:?(
??????????children
????????)}
??????
????);
??}
}
class?EditableTable?extends?React.Component<any,?any>?{
??formRef?=?React.createRef();
??//?React?Hook使用的?useForm,這里使用React.createRef代替
??isEditing?=?record?=>?record.key?===?this.props.state.editingKey;
??edit(record:?any)?{
????//?這里需要通過setFieldsValue
????this.formRef?.current?.setFieldsValue({
??????name:?'',
??????age:?'',
??????address:?'',
??????...record,
????});
????//?調(diào)用父組件的方法開始傳值
????this.props.handleEdit(record)
??};
??cancel?=?()?=>?{
????this.props.handleCancel()
??};
??save(key:?any)?{
????//?getFieldsValue獲取當前所選的行的值
????const?row?=?this.formRef?.current?.getFieldsValue();
????const?newData?=?[...this.props.state.data];
????//?根據(jù)索引匹配當前的數(shù)據(jù)
????const?index?=?newData.findIndex((item)?=>?key?===?item.key);
????if?(index?>?-1)?{
??????const?item?=?newData[index];
??????newData.splice(index,?1,?{...item,?...row});
????}?else?{
??????newData.push(row);
????}
????this.props.handleSave(newData)
??};
??render()?{
????const?components?=?{
??????//修改table該屬性默認行為
??????body:?{
????????cell:?EditableCell,
??????},
????};
????const?columns?=?[
??????{
????????title:?'name',
????????dataIndex:?'name',
????????width:?'25%',
????????editable:?true,
??????},
??????{
????????title:?'age',
????????dataIndex:?'age',
????????width:?'15%',
????????editable:?true,
??????},
??????{
????????title:?'address',
????????dataIndex:?'address',
????????width:?'40%',
????????editable:?true,
??????},
??????{
????????title:?'operation',
????????dataIndex:?'operation',
????????render:?(text,?record)?=>?{
??????????const?{editingKey}?=?this.props.state;
??????????const?editable?=?this.isEditing(record);
??????????return?editable???(
????????????
??????????????????????????onClick={()?=>?this.save(record.key)}
??????????????style={{
????????????????marginRight:?8,
??????????????}}
????????????>
??????????????Save
????????????
??????????????"Sure?to?cancel?" ?onConfirm={()?=>?this.cancel()}>
????????????????Cancel
??????????????
??????????
??????????)?:?(
????????????''}?onClick={()?=>?this.edit(record)}>
??????????????Edit
????????????
??????????);
????????},
??????},
????];
????const?mergedColumns?=?columns?.map(col?=>?{
??????if?(!col.editable)?{
????????return?col;
??????}
??????return?{
????????...col,
????????onCell:?record?=>?({
??????????record,
??????????inputType:?col.dataIndex?===?'age'???'number'?:?'text',
??????????dataIndex:?col.dataIndex,
??????????title:?col.title,
??????????editing:?this.isEditing(record),
????????}),
??????};
????});
????return?(
??????//?ref屬性是必須加的,這樣子組件才能使用form的屬性
?????? 