先說一下寫着篇文章的契機,是由於回顯,複雜表單的回顯,讓我以爲我對initialValue這個屬性是有誤解的。react
1、initialValue的出處和定義
initialValue的出處:git
AntDesign/Form表單件/getFieldDecorator(id,options)裝飾器函數/第二個參數options/options.initialValue。github
連接地址:https://ant.design/components/form-cn/#getFieldDecorator(id,-options)-%E5%8F%82%E6%95%B0antd
關於屬性initialValue,官方的解釋以下:app
關鍵字是「子節點的初始值」,初始值也就是默認值,好比Form中有一個城市的選擇器,默認選擇「杭州」,那麼initialValue就是杭州對應的value。函數
因此其實我一直覺得initialValue是defaultValue同樣的存在。工具
2、initialValue和defaultValue的區別
1. defaultValue的例子fetch
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中的值不更新。ui
Input組件沒有設置value屬性的話,就是一個非受控組件,它須要設置defaultValue,若是用戶不手動改變Input的輸入,那麼Input就一直顯示defaultValue指向的值(友情提示:值爲Input組件第一次被渲染時的真實值,變量或者常量指向的真實值)。這裏涉及到了受控組件和非受控組件的知識,不作延伸。this
2. 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);
貌似,表單的回顯出現一些起色。。。
3、碎碎念
不要一提表單回顯,就使勁往代碼裏面懟「setFieldsValue」,這樣會把代碼寫得很!很!很!很!很不優雅!!!
超級喜歡《鋒利的jQuery》封面上的這句話「每多學一點知識,就少寫一行代碼」,簡直是我寫代碼的信條。
數棧是雲原生—站式數據中臺PaaS,咱們在github和gitee上有一個有趣的開源項目:FlinkX,FlinkX是一個基於Flink的批流統一的數據同步工具,既能夠採集靜態的數據,也能夠採集實時變化的數據,是全域、異構、批流一體的數據同步引擎。你們喜歡的話請給咱們點個star!star!star!
github開源項目:https://github.com/DTStack/flinkx
gitee開源項目:https://gitee.com/dtstack_dev_0/flinkx