antd <Row> <Col> 动态添加问题

新手上路,请多包涵

问题描述

对一个数组进行动态JSX拼接,目前是三条数据需要用Row包裹起来。

问题出现的环境背景及自己尝试过哪些方法

实现row和col的动态生成,我试过动态拼接,可是编译不过去.

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)
const formItems = data.map((item) => (

<FormItem label={item.name} key={item.name}>
  <Row>
    {item.list.map((value) => <Col span={8}><Checkbox key={value.name}>{value.name}</Checkbox></Col>)}
  </Row>
</FormItem>

));

你期待的结果是什么?实际看到的错误信息又是什么?

我希望的是<Row><Col/><Col/><Col/></Row>目前是<Row><Col/>...</Row>这样的结果

阅读 21.4k
2 个回答
新手上路,请多包涵

遇到同样的问题,而且想想其实也是常见的场景,经过半天周折做出的自己的解决方案,希望群策群力,提出更优的方案。

背景:对一个数组进行动态JSX拼接,目前是三条数据需要用Row包裹起来。
场景:原项目中对于这里的处理是穷举法,对所有的Col做写死三个一个Row,写出形式如下:

<div>
  <Row>
    <Col span="8">
      <FormItem {...formItemLayout} label="真实姓名:">
        <Input {...getFieldProps('realName', { initialValue: '' }) } disabled={true} style={{border:'none', background:'#FFF', display:'block'}}/>
      </FormItem>
    </Col>
    <Col span="8">
      <FormItem {...formItemLayout} label="性别:">
        <Input {...getFieldProps('sex', { initialValue: '' }) } disabled={true} style={{border:'none', background:'#FFF', display:'block'}}/>
      </FormItem>
    </Col>
    <Col span="8">
      <FormItem {...formItemLayout} label="年龄:">
        <Input {...getFieldProps('age', { initialValue: '' }) } disabled={true} style={{border:'none', background:'#FFF', display:'block'}}/>
      </FormItem>
    </Col>
  </Row>
  <Row>
    <Col span="8">
      <FormItem {...formItemLayout} label="身份证号码:">
        <Input {...getFieldProps('idNo', { initialValue: '' }) } disabled={true} style={{border:'none', background:'#FFF', display:'block'}}/>
      </FormItem>
    </Col>
    <Col span="8">
      <FormItem {...formItemLayout} label="银行卡号:">
        <Input {...getFieldProps('cardNo', { initialValue: '' }) } disabled={true} style={{border:'none', background:'#FFF', display:'block'}}/>
      </FormItem>
    </Col>
    <Col span="8">
      <FormItem {...formItemLayout} label="所属银行:">
        <Input {...getFieldProps('bank', { initialValue: '' }) } disabled={true} style={{border:'none', background:'#FFF', display:'block'}}/>
      </FormItem>
    </Col>
  </Row>
...
</div>

这样写的问题显而易见,变动成本很高,如果要在原有布局上中间插入一个新的Col,需要手动把该项后面的Col依次推后一位,大量的手工劳动(这样写代码真的是在搬砖),好处也有,就是代码直观易懂,新手也能上手改动,代码的格式就能直观映射出在屏幕上的布局。
分析:这里无非就是想对一个可能变动的数组进行三个一组显示一行,超出三个的换行显示

举例

思路:
1、对数据分组
2、遍历分组后的数组生成Dom
3、在JSX中渲染显示
具体步骤:
1、数组如下

const rowList = [
  {
    label: '真实姓名:',
    propKey: 'realName',
  },
  {
    label: '性别:',
    propKey: 'sex',
  },
  {
    label: '年龄:',
    propKey: 'age',
  },
  {
    label: '身份证号码:',
    propKey: 'idNo',
  },
  {
    label: '银行卡号:',
    propKey: 'cardNo',
  },
  {
    label: '所属银行:',
    propKey: 'bank',
  },
...
]

数组中的键仅保留标示性的属性,这样在增加新的数组项时可以保证最少改动,对于公共属性做数组遍历添加

// 为单元对象统一添加属性
for (let i = 0; i < rowList.length; i++) {
  const eachObj = rowList[i];
  if (eachObj.initialValue === undefined) {
    eachObj.initialValue = '';
  }
  if (eachObj.disabled === undefined) {
    eachObj.disabled = true;
  }
  if (eachObj.style === undefined) {
    eachObj.style = {border:'none', background:'#FFF', display:'block'}
  }
}

对数组进行遍历,把三个放入一组

for (let i = 0; i < rowList.length; i++) {
  if (i % 3 === 0) {
    const rowObjFirst = rowList[i];
    const rowObjSecond = rowList[i+1];
    const rowObjThird = rowList[i+2];
    tableDomList.push({
        <Col span="8">
          <FormItem {...formItemLayout} label={rowObjFirst.label}>
            <Input {...getFieldProps(rowObjFirst.propKey, { initialValue: rowObjFirst.initialValue }) } 
              disabled={rowObjFirst.disabled} 
              style={rowObjFirst.style}/>
          </FormItem>
        </Col>
        <Col span="8">
          <FormItem {...formItemLayout} label={rowObjSecond.label}>
            <Input {...getFieldProps(rowObjSecond.propKey, { initialValue: rowObjSecond.initialValue }) } 
              disabled={rowObjSecond.disabled} 
              style={rowObjSecond.style}/>
          </FormItem>
        </Col>
        <Col span="8">
          <FormItem {...formItemLayout} label={rowObjThird.label}>
            <Input {...getFieldProps(rowObjThird.propKey, { initialValue: rowObjThird.initialValue }) } 
              disabled={rowObjThird.disabled} 
              style={rowObjThird.style}/>
          </FormItem>
        </Col>
    })
  }
}

遍历分组后的数组生成Dom

tableDom = tableDomList.map((ele) => {
  return ele
})

渲染显示

return (
  <Form horizontal form={this.props.form} style={{ marginTop: '20' }}>
    <div className="navLine-wrap-left">
      <h2>基本信息</h2>
      {
        tableDom
      }
    </div>
  </Form>
)

总结:这种方案很明显还不够最优,并没有做到DRY(Don't repeat yourself),代码中还充斥着雷同部分,可以做进一步抽象优化,但是相比较原先穷举的方案,改良后对于数据变更的处理可以少一些手动改动,在变动较小的情况下,可以直接在数组需要插入的位置直接添加数据项即可,该程序会自动遍历数据项做三个一组分组进行显示

Ref:示例中使用到Antd的行列布局,即对空间的横向以Col分割,纵向按Row划分,所以才产生了这个场景,开发者可以针对自己需要的分组布局,对数据进行分组处理,做类似上面的显示布局

新手上路,请多包涵

你要的是不是这个效果...,imgs参数是图片,自己弄个几个链接就行了...

 const imgCols = [];

 for (let i = 0; i < imgs.length; i+=3) {

 const rowArr = imgs.slice(i, i+3);

 const ele = (

 <>

 <Row>

 {

 rowArr.map((item, j)=>{

 return (

 <Col md={8} sm={24} key={j+i}>

 <img src={item} width="100%" style={{border:'1px solid #ddd', borderRadius:10}}/>

 </Col>

 )

 })

 }

 </Row>

 </>

 )

 imgCols.push(ele);

 }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏