先说一下写着篇文章的契机,是由于回显,复杂表单的回显,让我以为我对initialValue这个属性是有误解的。react
1、initialValue的出处和定义git
initialValue的出处:github
AntDesign/Form表单件/getFieldDecorator(id,options)装饰器函数/第二个参数options/options.initialValue。antd
连接地址:https://ant.design/components...
关于属性initialValue,官方的解释以下:app
关键字是“子节点的初始值”,初始值也就是默认值,好比Form中有一个城市的选择器,默认选择“杭州”,那么initialValue就是杭州对应的value。函数
因此其实我一直觉得initialValue是defaultValue同样的存在。工具
2、initialValue和defaultValue的区别fetch
import React, { Component,Fragment } from 'react';
import { Button,Input } from "antd";
export default class CreateFrom extends Component {
state={value:"value"}
updateValue = () => {ui
this.setState({value:"newValue"})
}
render() {this
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组件第一次被渲染时的真实值,变量或者常量指向的真实值)。这里涉及到了受控组件和非受控组件的知识,不作延伸。
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);
貌似,表单的回显出现一些起色。。。
3、碎碎念
不要一提表单回显,就使劲往代码里面怼“setFieldsValue”,这样会把代码写得很!很!很!很!很不优雅!!!
超级喜欢《锋利的jQuery》封面上的这句话“每多学一点知识,就少写一行代码”,简直是我写代码的信条。
数栈是云原生—站式数据中台PaaS,咱们在github和gitee上有一个有趣的开源项目:FlinkX,FlinkX是一个基于Flink的批流统一的数据同步工具,既能够采集静态的数据,也能够采集实时变化的数据,是全域、异构、批流一体的数据同步引擎。你们喜欢的话请给咱们点个star!star!star!
github开源项目:https://github.com/DTStack/fl...
gitee开源项目:https://gitee.com/dtstack_dev...