elementUI 多层结构动态生成el-form及校验

发布时间 2023-05-09 10:32:14作者: 浪里小韭菜

如题,当整个el-form 都是通过多层数据结构循环渲染出来的表单,

那么每个el-form-item的prop和el-input、el-select等的v-model也是动态变量填充

怎么样才能内嵌rules校验呢?

如下数据结构:

// form通过initData数据结构进行渲染
const initData = [
  {
    channel: 'sms',
    title: '短信频控',
    ref: 'smsFormRef',
    model: 'smsFreqObj',
    icon: 'el-icon-message',
    state: true, 
    lists: [
      {
        title: '全局频控',
        titTip: '',
        options: [
          {
            type: 'select',
            title: '频控分组',
            key: 'freqGroup',
            defaultVal: '0',
            placeholder: '请选择频控分组',
            options: [
              { code: '0', name: '默认频控' },
              { code: '1', name: '特殊策略' },
            ]
          },
          {
            type: 'input',
            key: 'freqConfig',
            defaultVal: [
              ['1', ''],
              ['7', '']
            ]
          }
        ]
      }
    ]
  }
]

// 表单数据收集
data(){
    return {
        freqObj: {
            smsFreqObj: {
                freqGroup: '',
                freqConfig: [
                  ["1", ""],
                  ['7', '']
                ],
            }
        }
    }
}
<template>
  <div class="frequency-list overflow-page">
    <el-card class="search-wrap el-card-8">
       // 折叠面板控件
      <el-collapse v-model="activeNames">
         // 从这里开始进入initData多层循环
        <el-collapse-item v-for="init in initData" :title="init.title" :name="init.channel">
           // 循环多个表单
          <el-form :inline="true" :disabled="init.state" :rules="freqRules" :ref="init.ref" :model="freqObj[init.model]" class="content-wrap" label-width="80px">
            <template v-for="list in init.lists">
              <p class="ctn-tit">
                <span>{{ list.title }}</span>
              </p>
              <template v-for="item in list.options">
                 // 重点来了,:prop 直接使用 当前的item.key,不需要要层层嵌套
                <el-form-item 
                  v-if="item.type === 'select'" 
                  :label="item.title" 
                  :prop="item.key"
                  :rules="{ required: true, message: '请选择频控分组', trigger: 'change' }"
                >
                   // v-model 动态变量
                  <el-select v-model="freqObj[init.model][item.key]" size="medium" :placeholder="item.placeholder">
                    <el-option v-for="option in item.options" :key="option.code" :label="option.name" :value="option.code"></el-option>
                  </el-select>
                </el-form-item>

                <div class="config-item" v-else-if="item.type === 'input'">
                  <div v-for="(config, idx) in item.defaultVal">
                    <span class="txt mr-10">每个用户</span>
                     // 重点来了,:prop 直接使用 当前的item.key + '.' + idx + '.0' ,注意这个数据结构为二维数组[ ['1', ''], ['7', ''] ]
                    <el-form-item 
                    :prop="item.key + '.' + idx + '.0' "
                    :rules="{ required: true, message: '请输入天数', trigger: 'blur' }"
                    >
                      <el-input placeholder="请输入" disabled clearable v-model.number="freqObj[init.model][item.key][idx][0]" size="medium" class="input-txt"></el-input>
                    </el-form-item>
                    <span class="txt mr-10">天内,最多接收</span>
                    <el-form-item 
                    :prop="item.key + '.' + idx + '.1' "
                      :rules="{ required: true, message: '请输入短信条数', trigger: 'blur' }"
                    >
                      <el-input placeholder="请输入" clearable v-model.number="freqObj[init.model][item.key][idx][1]" size="medium" class="input-txt"></el-input>
                    </el-form-item>
                    <span class="txt mr-10">条短信</span>
                  </div>
                </div>
              </template>
            </template>
          </el-form>
        </el-collapse-item>
      </el-collapse>
    </el-card>
  </div>
</template>