循环设置多个ref及多表单验证(vue3+ts)

具体界面效果是看不到啦,以前的项目,离了后台看不到

html代码
  <div class="form-list" v-if="formTableShow">
    <el-form
      v-for="(item, index) in formList"
      :ref="(el: any) => { setItemRef(el, index)}"
      :model="dataForm['form' + index]"
      :rules="rules['form' + index]"
      :size="formConfigs.size"
      :label-width="formConfigs.labelWidth"
      :inline="formConfigs.inline"
      :label-position="formConfigs.labelPosition"
      :disabled="formConfigs.disabled"
      :status-icon="formConfigs.statusIcon"
    >
      <el-form-item
        :label="foitem.label"
        :prop="foitem.prop"
        :label-width="foitem.labelWdith || 'auto'"
        v-for="foitem in item.forms"
      >
        <el-input v-model="dataForm['form' + index][foitem.prop]"></el-input>
      </el-form-item>
    </el-form>
    <div class="dialog-footer">
      <el-button type="primary" @click="submitRule">保存</el-button>
    </div>
  </div>

PS: 这个分享乃以前项目封装的一个动态表单提取出来的部分,完整的很复杂,功能有以下几点:

  1. 同一个vue文件,展示100多种表格,表格的表头等信息全由接口返回
  2. 所有表格的新增、修改、查看都用同一个弹窗组件,弹窗里面有多种情况(单个表单、多个表单、多个表单和多个表格),其中表格里面也是表单可以编辑且有表单验证,每部分还可能有自己的标题,甚至某些表头或label也有tooltip提示信息
  3. 弹窗内所有表单/表格的所有信息(label、表头、字段、验证…)都由后端配置接口返回,部分复杂的多表单多表格内容因太复杂就由前端自己配置了

鉴于功能及其代码太复杂便不贴出来了

ts部分
<script lang="ts" setup>
import {
  ref,
  reactive,
  computed,
} from 'vue'
import { FormRules } from 'element-plus'
interface FormItem {
  prop: string // 表单字段
  label: string // 表单label
  labelWdith?: string // 表单宽度
  formtype?: string // 表单类型
  defaultValue?: any // 默认值
  rule?: any // 表单验证配置
  config?: any // 表单原生配置
}
// 所有表单配置----这部分是props传入的,提取后稍微改了下
const formList: any = [
  {
    title: 'string',
    forms: [
      {
        //   prop: 'string',              // 字段       必
        //   label: 'string',             // 表单名     必
        //   labelWdith: 'string',        // 表单名宽度 非比 默认:auto
        //   rule: {}                     // 验证规则
        //   ...
      },
      {
        //   prop: 'string',              // 字段       必
        //   label: 'string',             // 表单名     必
        //   labelWdith: 'string',        // 表单名宽度 非比 默认:auto
        //   rule: {}                     // 验证规则
        //   ...
      }
      // ....
    ]
  },
  {
    title: 'string',
    forms: [
      {
        //   prop: 'string',              // 字段       必
        //   label: 'string',             // 表单名     必
        //   labelWdith: 'string',        // 表单名宽度 非比 默认:auto
        //   rule: {}                     // 验证规则
        //   ...
      },
      {
        //   prop: 'string',              // 字段       必
        //   label: 'string',             // 表单名     必
        //   labelWdith: 'string',        // 表单名宽度 非比 默认:auto
        //   rule: {}                     // 验证规则
        //   ...
      }
      // ....
    ]
  }
]
// 表单总体配置
const formConfigs = computed(() => {
  return {
    size: 'default',
    labelWidth: 'auto',
    inline: false,
    labelPosition: 'right',
    disabled: false,
    statusIcon: false,
    ...props.formConfig // 传入的表单公共配置
  }
})
// 所有表单表格配置
const formTableShow = ref(false) 	// 为了解决动态处理验证规则后自动启动验证
const dataForm: any = ref({}) 		// 多套表单字段
const rules: any = reactive({}) 	// 多套验证规则
let resetForm = reactive({}) 		// 为了重置按钮的点击效果
const refList: any = reactive({}) 	// 多个ref
// 初始化表单
const initForm = async () => {
  // 处理多套表单或者表格的dataForm和验证规则
  await formList.map((item: any, index: number) => {
    dataForm.value['form' + index] = {}
    rules['form' + index] = <FormRules>{}
    item.forms?.map((foitem: FormItem) => {
      // 设置表单字段
      dataForm.value['form' + index][foitem.prop] =
        foitem.defaultValue === undefined
          ? foitem.formtype === 'inputnumber'
            ? undefined
            : foitem.formtype === 'picker' &&
              foitem.config?.type?.includes('range')
            ? []
            : ''
          : foitem.defaultValue
      // 设置验证规则
      if (foitem.rule?.message) {
        // 验证规则
        rules['form' + index][foitem.prop] = [
          {
            required:
              foitem.rule.required === undefined ? false : foitem.rule.required,
            message: foitem.rule.message || '请输入',
            trigger: foitem.rule.trigger || 'blur'
          }
        ]
      }
      // 获取字典
      getDict(foitem)
    })
  })
  // 初始化完成再渲染表单表格,负责验证不起效
  formTableShow.value = true
  // 为了重置表单
  resetForm = { ...dataForm.value }
}

// 设置多个ref
const setItemRef = (el: any, index: number) => {
  if (el) {
    refList['ref' + index] = el
  }
}
// 数据提交验证
const formRule = ref(false) // 表单是否通过,和表格相反
const submitRule = async () => {
  await formList.map((item: any, index: number) => {
    refList['ref' + index]?.validate((valid: any, props: any) => {
      if (valid) {
        formRule.value = true
      } else {
        formRule.value = false
      }
    })
  })
  setTimeout(() => {
    // 如果都通过则提交
    if (formRule.value) {
      submitAll()
    }
  }, 100)
}
</script>

当初为了这个功能,掉了不晓得多少头发,趁空闲时间,便记录下来部分

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3和TypeScript中,可以通过表单来修改多条数据。下面是一个示例,展示如何使用表单同时修改多条数据: 首先,在Vue组件中定义一个数据对象,用来保存多条数据的表单值: ```vue <template> <form @submit="handleSubmit"> <div v-for="item in items" :key="item.id"> <input v-model="formValues[item.id].name" type="text" /> <input v-model="formValues[item.id].age" type="number" /> </div> <button type="submit">保存</button> </form> </template> <script setup lang="ts"> import { reactive, ref } from 'vue'; interface Item { id: number; name: string; age: number; } const items: Item[] = [ { id: 1, name: 'John', age: 25 }, { id: 2, name: 'Jane', age: 30 }, // ... ]; const formValues = reactive<{ [key: number]: Item }>({}); items.forEach((item) => { formValues[item.id] = { ...item }; }); function handleSubmit() { // 处理表单提交逻辑 // 可以在这里将修改后的数据发送给后端进行保存 console.log(Object.values(formValues)); } </script> ``` 在上述代码中,我们使用了Vue的Composition API来定义响应式的数据对象。`formValues`对象用于保存多条数据的表单值,以每个数据项的id作为键。 在模板中使用`v-for`指令遍历`items`数组,并使用`v-model`指令绑定输入框的值到`formValues`对象上。这样,当用户输入内容时,`formValues`中对应数据项的值会自动更新。 在提交表单时,可以通过`Object.values(formValues)`获取到修改后的数据数组,并进行进一步的处理,例如将数据发送给后端进行保存。 请注意,上述代码使用了Vue 3的新特性 `<script setup>`,可以更简洁地编写组件逻辑。如果你选择使用Options API,可以将相关逻辑放在`data`、`methods`等选项中。 这只是一个简单的示例,你可以根据实际业务需求进行修改和扩展,例如添加校验、数据同步等逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值