美文网首页
数栈技术文章分享:你居然是这样的initialValue

数栈技术文章分享:你居然是这样的initialValue

作者: 袋鼠云数栈 | 来源:发表于2021-05-11 19:14 被阅读0次

    先说一下写着篇文章的契机,是因为回显,复杂表单的回显,让我觉得我对initialValue这个属性是有误解的。

    一、initialValue的出处和定义

    initialValue的出处:

    AntDesign/Form表单件/getFieldDecorator(id,options)装饰器函数/第二个参数options/options.initialValue。

    链接地址:https://ant.design/components/form-cn/#getFieldDecorator(id,-options)-%E5%8F%82%E6%95%B0

    关于属性initialValue,官方的解释如下:

    关键字是“子节点的初始值”,初始值也就是默认值,比如Form中有一个城市的选择器,默认选择“杭州”,那么initialValue就是杭州对应的value。

    所以其实我一直以为initialValue是defaultValue一样的存在。

    二、initialValue和defaultValue的区别

    1. 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组件第一次被渲染时的真实值,变量或者常量指向的真实值)。这里涉及到了受控组件和非受控组件的知识,不做延伸。

    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);

    貌似,表单的回显出现一些转机。。。

    三、碎碎念

    不要一提表单回显,就使劲往代码里面怼“setFieldsValue”,这样会把代码写得很!很!很!很!很不优雅!!!

    超级喜欢《锋利的jQuery》封面上的这句话“每多学一点知识,就少写一行代码”,简直是我写代码的信条。

    数栈是云原生—站式数据中台PaaS,我们在github和gitee上有一个有趣的开源项目:FlinkXFlinkX是一个基于Flink的批流统一的数据同步工具,既可以采集静态的数据,也可以采集实时变化的数据,是全域、异构、批流一体的数据同步引擎。大家喜欢的话请给我们点个star!star!star!

    github开源项目:https://github.com/DTStack/flinkx

    gitee开源项目:https://gitee.com/dtstack_dev_0/flinkx

    相关文章

      网友评论

          本文标题:数栈技术文章分享:你居然是这样的initialValue

          本文链接:https://www.haomeiwen.com/subject/nnendltx.html