共计 4559 个字符,预计需要花费 12 分钟才能阅读完成。
先说一下写着篇文章的契机,是因为回显,简单表单的回显,让我感觉我对 initialValue 这个属性是有误会的。
一、initialValue 的出处和定义
initialValue 的出处:
AntDesign/Form 表单件 /getFieldDecorator(id,options) 装璜器函数 / 第二个参数 options/options.initialValue。
链接地址:https://ant.design/components…
对于属性 initialValue,官网的解释如下:
关键字是“子节点的初始值”,初始值也就是默认值,比方 Form 中有一个城市的选择器,默认抉择“杭州”,那么 initialValue 就是杭州对应的 value。
所以其实我始终认为 initialValue 是 defaultValue 一样的存在。
二、initialValue 和 defaultValue 的区别
- defaultValue 的例子
import React, {Component,Fragment} from ‘react’;
import {Button,Input} from “antd”;
export default class CreateFrom extends Component {
state={value:”value”}
updateValue = () => {
this.setState({value:"newValue"})
}
render() {
return (
<Fragment>
<Button onClick={this.updateValue}> 更新 value</Button>
<Input defaultValue={this.state.value} />
</Fragment>
);
}
}
阐明:当该组件被渲染时,Input 中的值为”value“,当我点击“更新 value 按钮”时,Input 中的值不更新。
Input 组件没有设置 value 属性的话,就是一个非受控组件,它须要设置 defaultValue,如果用户不手动扭转 Input 的输出,那么 Input 就始终显示 defaultValue 指向的值(情谊提醒:值为 Input 组件第一次被渲染时的实在值,变量或者常量指向的实在值)。这里波及到了受控组件和非受控组件的常识,不做延长。
- intialValue 的例子
1)models/list.js
let count = 1;
const CITY = [“ 杭州 ”,” 北京 ”,” 上海 ”,” 广州 ”,” 深圳 ”];
export default {
namespace: ‘list’,
state: {
citys: CITY,
detail:{city:CITY[count%5],count}
},
effects: {
*fetchDetail({payload}, {call, put}) {
// 不发申请, 而是间接更新 reducer
// const response = yield call(service, payload);
count++;
yield put({
type: 'queryDetail',
payload: {city:CITY[count%5],count},
});
},
},
reducers: {
queryDetail(state, action) {
return {
...state,
detail: action.payload,
};
}
},
};
2)router 组件文件
import React, {Component} from ‘react’;
import {connect} from “dva”;
import {InputNumber,Select,Form,Button} from “antd”;
const FormItem = Form.Item;
const {Option} = Select;
const formItemLayout = {
labelCol: {
xs: {span: 24},
sm: {span: 2},
},
wrapperCol: {
xs: {span: 24},
sm: {span: 22},
},
};
@connect(({list})=>({
citys:list.citys,
detail:list.detail
}))
class CreateFrom extends Component {
getDetail = () => {
this.props.dispatch({type:"list/fetchDetail"});
}
render() {
const {form,detail={},citys=[]} = this.props;
const {getFieldDecorator} = form;
const {city,count} = detail;
return (
<Form>
<Button onClick={this.getDetail}> 从新获取数据 </Button>
<FormItem
{...formItemLayout}
label="城市"
>
{getFieldDecorator('city', {
initialValue: city,
rules: [{required: true, message: '请抉择城市'}],
})(<Select style={{width:160}} placeholder="请抉择城市">
{citys.map(item=><Option key={item} value={item}>{item}</Option>)
}
</Select>
)}
</FormItem>
<FormItem
{...formItemLayout}
label="总量"
>
{getFieldDecorator('count', {
initialValue:count,
rules: [{required: true, message: '总量 (1-99999999)',pattern:/^[1-9][0-9]{0,7}$/ }],
})(<InputNumber style={{width:160}}/>
)}
</FormItem>
</Form>
);
}
}
export default Form.create()(CreateFrom);
阐明:当该 Form 组件被渲染时,接管 props.detail,因为在 models/list.js 文件的 state 中曾经初始化,所以,第一次 render 被渲染的值是“杭州”和“1”,点击“从新获取数据按钮”,这个时候 props.detail 扭转为 {city:” 北京 ”,count:2},与此同时 Form 被渲染的值也随之扭转。
uhmmm,怎么和 defaultValue 的体现形式不一样?不是说好是默认值的嘛?不是说好不会跟着数据的扭转而扭转的嘛?逗我玩还是~
敲黑板,划重点,initialValue 值能够被更新,除了上面两种状况:
1. 用户手动更新表单数据,比方在 <Input /> 组件中手动输出,在 <Select /> 组件中手动抉择等等,在用户手动更新数据之后,initialValue 的值扭转不会更新表单值。2. 当执行了 setFieldsValue 办法之后,initialValue 的值扭转不会更新表单值。
上面的例子中在生命周期函数 componentDidMount 中执行了 setFieldsValue 办法,其余不变,你会发现不管怎么点击“从新获取数据按钮”,城市对应的值都不会被更新,而总量对应的值却始终在更新。如果你手动扭转总量的输出,再点击“从新获取数据按钮”,此时城市和总量的值都不会被更新。
import React, {Component} from ‘react’;
import {connect} from “dva”;
import {InputNumber,Select,Form,Button} from “antd”;
const FormItem = Form.Item;
const {Option} = Select;
const formItemLayout = {
labelCol: {
xs: {span: 24},
sm: {span: 2},
},
wrapperCol: {
xs: {span: 24},
sm: {span: 22},
},
};
@connect(({list})=>({
citys:list.citys,
detail:list.detail
}))
class CreateFrom extends Component {
componentDidMount(){
this.props.form.setFieldsValue({city:"上海"});
}
getDetail = () => {
this.props.dispatch({type:"list/fetchDetail"});
}
render() {
const {form,detail={},citys=[]} = this.props;
const {getFieldDecorator} = form;
const {city,count} = detail;
return (
<Form>
<Button onClick={this.getDetail}> 从新获取数据 </Button>
<FormItem
{...formItemLayout}
label="城市"
>
{getFieldDecorator('city', {
initialValue: city,
rules: [{required: true, message: '请抉择城市'}],
})(<Select style={{width:160}} placeholder="请抉择城市">
{citys.map(item=><Option key={item} value={item}>{item}</Option>)
}
</Select>
)}
</FormItem>
<FormItem
{...formItemLayout}
label="总量"
>
{getFieldDecorator('count', {
initialValue:count,
rules: [{required: true, message: '总量 (1-99999999)',pattern:/^[1-9][0-9]{0,7}$/ }],
})(<InputNumber style={{width:160}}/>
)}
</FormItem>
</Form>
);
}
}
export default Form.create()(CreateFrom);
貌似,表单的回显呈现一些转折。。。
三、碎碎念
不要一提表单回显,就使劲往代码外面怼“setFieldsValue”,这样会把代码写得很!很!很!很!很不优雅!!!
超级喜爱《尖锐的 jQuery》封面上的这句话“每多学一点常识,就少写一行代码”,几乎是我写代码的信条。
数栈是云原生—站式数据中台 PaaS,咱们在 github 和 gitee 上有一个乏味的开源我的项目:FlinkX,FlinkX 是一个基于 Flink 的批流对立的数据同步工具,既能够采集动态的数据,也能够采集实时变动的数据,是全域、异构、批流一体的数据同步引擎。大家喜爱的话请给咱们点个 star!star!star!
github 开源我的项目:https://github.com/DTStack/fl…
gitee 开源我的项目:https://gitee.com/dtstack_dev…