引言

在中后台系统的日常开发中,表单必不可少,当表单内容比较多,例如有上百个字段(这一点都不夸张,血淋淋的现实)时,代码往往也变得复杂且难以维护,加上各种动态联动的表单校验,无疑让我们的页面开发过程雪上加霜,本文将结合自己平时的开发习惯,分享一下在大表单开发中如何处理复杂的表单校验,以及如何对表单进行拆分,减少单个文件堆积过多的代码内容。

表单校验

<template>
  <el-form
    ref="ruleForm"
    :rules="rules"
    :model="form"
    inline
  >
    <el-form-item label="企业性质" prop="natureEnterprise">
      <el-select v-model="form.natureEnterprise">
        <el-option
          label="国企"
          :value="1"
        />
        <el-option
          label="事业单位"
          :value="2"
        />
        <el-option
          label="个体户"
          :value="3"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="业务类型" prop="type">
      <el-select v-model="form.type">
        <el-option
          label="护肤"
          :value="1"
        />
        <el-option
          label="食品"
          :value="2"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="企业名称" prop="name">
      <el-input v-model="form.name" placeholder="请输入"></el-input>
    </el-form-item>
    <el-form-item label="社会统一信用代码" prop="creditCode">
      <el-input v-model="form.creditCode" placeholder="请输入"></el-input>
    </el-form-item>
    <el-form-item label="注册地址" prop="address">
      <el-input v-model="form.address" placeholder="请输入"></el-input>
    </el-form-item>
  </el-form>
</template>
<script>
export default {
    data() {
        return {
          form: {
            natureEnterprise: null,
            type: null,
            address: '',
            name: '',
            creditCode: ''
          },
          rules: {
            natureEnterprise: [
              { required: true, message: '企业性质不能为空', trigger: 'change' }
            ],
            type: [
              { required: true, message: '业务类型不能为空', trigger: 'change' }
            ],
            address: [
              { required: true, message: '注册地址不能为空', trigger: 'change' }
            ],
            name: [
              { required: true, message: '企业名称不能为空', trigger: 'change' }
            ],
            creditCode: [
              { required: true, message: '社会统一信用代码不能为空', trigger: 'change' }
            ]
          }
        }
    }
}
</script>

以上表单为例,要求默认全部必填,如果企业性质为个体户,则注册地址和社会统一信用代码为非必填,让我们增加以下代码来实现这个需求:

watch: {
  'form.natureEnterprise': {
    hanlder(val) {
      this.rules.creditCode[0].required = val !== 3
      this.rules.address[0].required = val !== 3
    }
  }
}

如果此时新增一个校验,假设要求业务类型为护肤时,企业名称非必填,那我们需要像上面监听业务类型的值然后做相应的判断,随着表单内容的增多,我们的watch会越来越多,同时rules也会散落在不同的地方,这必然会为后续的代码维护带来困难,接手的人也必须小心翼翼的在上面做修改。

使用computed进行表单校验优化

将rules作为计算属性里的值统一处理,而不是放在data里,避免需要频繁去操作data里的rules,也避免rules的项散落在页面各处。

computed: {
  rules({ form }) {
      // 是否个体户
    const isSelfEmploy = form.natureEnterprise === 3
    return {
      natureEnterprise: [
        { required: true, message: '企业性质不能为空', trigger: 'change' }
      ],
      type: [
        { required: true, message: '业务类型不能为空', trigger: 'change' }
      ],
      name: [
        { required: true, message: '企业名称不能为空', trigger: 'change' }
      ],
      address: [
        { required: !isSelfEmploy, message: '注册地址不能为空', trigger: 'change' }
      ],
      creditCode: [
        { required: !isSelfEmploy, message: '社会统一信用代码不能为空', trigger: 'change' }
      ]
    }
  }
}

改用computed后,会有一个问题:页面初始加载或computed里使用的相关值改变时会立即触发检验。看起来体验不是很好,el-form有一个validate-on-rule-change属性,表示会在rules属性改变后立即触发一次验证,默认为true,将其设置为false即可

<el-form
  :validate-on-rule-change="false"
></el-form>

表单拆分

当表单内容变得庞大时,将其塞在一个文件里进行开发时无疑会变得很臃肿。这时候我们可以将其拆分成一个一个的组件,每个组件里独立负责自己的表单内容以及校验,最后提交时由父组件统一收集每个子组件的数据进行提交,这样避免了所有内容都放在一个文件里变得大而杂,同时也有利于团队多人进行开发,减少冲突。

// 父组件:main-form.vue
<template>
  <!-- 子组件-基础信息表单 -->
  <base-form ref="baseFormRef" />
  <!-- 子组件-合作信息表单 -->
  <coop-form ref="coopFormRef" />
  <el-button type="primary" @click="handleSave">保存</el-button>
</template>
<script>
import BaseForm from './base-form'
import CoopForm from './coop-form'
export default {
  components: {
    BaseForm,
    CoopForm
  },
  methods: {
    async handleSave() {
      // 调用子组件提供的方法,获取表单数据
      const baseFormData = await this.$refs['baseFormRef'].validate()
      const coopFormData = await this.$refs['coopFormRef'].validate()
      if (baseFormData && coopFormData) {
        // 如果校验通过,拼接子组件数据进行提交
        const mainFormData = {
          ...baseFormData,
          ...coopFormData
        }
        // 提交数据
        await saveApi(mainForm)
        this.$message.success('保存成功!')
      }
    }
  }
}
</script>

子组件负责处理自己的内容,同时提供方法给父组件调用,在方法里进行校验,校验通过后再返回自身的表单数据给父组件。

// 子组件示例:base-form.vue
<template>
  <el-form ref="ruleForm" :model="form" :rules="rules">
  </el-form>
</template>
<script>
export default {
  data() {
    return {
      form: {
        // ...
      },
      rules: {
        // ...
      }
    }
  },
  methods: {
    // 提供给父组件的方法并返回表单数据
    validate() {
      return new Promise(resolve => {
        this.$refs['ruleForm'].validate(valid => {
          // 校验通过返回表单数据,反之,返回null
          if (valid) {
            resolve(this.form)
          } else {
            resolve(null)
          }
        })
      })
    }
  }
}
</script>

表单兄弟组件的数据通信问题

将大表单拆分后,有些时候兄弟组件间需要通信,例如coop-form里的某个字段需要根据base-form的某个字段来决定是否必填。我通常选择使用vuex解决,在base-form的值变化时将其保存到vuex里,coop-form则可以从vuex里获取,然后进行自己的逻辑处理。

// vuex里新建文件用来存放表单通信数据
// src/store/modules/formDta.js
export default {
  namespaced: true,
  state: {
    natureEnterprise: ''
  },
  mutations: {
    SET_NATURE_ENTERPRISE(state, payload) {
      state.natureEnterprise = payload
    }
  }
}
// src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import formData from './modules/formData.js'
Vue.use(Vuex)
export default new Vuex.Store({
  modules: {
    formData
  }
})
// base-form.vue
watch: {
  'form.natureEnterprise': {
    handler(val) {
      // 将企业性质的值存储到vuex里
      this.$store.commit('formData/SET_NATURE_ENTERPRISE', val)
    }
  }
}
// coop-form.vue
computed: {
  ...mapState('formData', [
    'natureEnterprise'
  ]),
  rules() {
    return {
      address: [
        { required: this.natureEnterprise === 1, message: '注册地址不能为空', trigger: 'change' }
      ]
    }
  }
}

以上就是vue开发中后台系统复杂表单优化技巧的详细内容,更多关于vue后台系统复杂表单优化的资料请关注Devmax其它相关文章!

vue开发中后台系统复杂表单优化技巧的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. Swift思量与初探:我需要学习Swift吗?

    最近,除了N多的基于Swift的服务端开发框架,笔者不由深思,到底该这么评价Swift呢?前两点在Swift的语法和语言特性中已经表现得淋漓尽致:像是尾随闭包,枚举关联值,可选值和强制的类型安全等都是Swift显而易见的优点。综上所述,Swift拥有着被广泛使用以及当做第一学习语言的潜质。Swift在语法层次上会更加高级,并且Swift并没有使用GC机制,因此可以与C更好地相兼容。Swift中的注释与C语言的注释非常相似。

  3. vue自定义加载指令v-loading占位图指令v-showimg

    这篇文章主要为大家介绍了vue自定义加载指令和v-loading占位图指令v-showimg的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. vue使用动画实现滚动表格效果

    这篇文章主要为大家详细介绍了vue使用动画实现滚动表格效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. 关于Vue 监控数组的问题

    这篇文章主要介绍了Vue 监控数组的示例,主要包括Vue 是如何追踪数据发生变化,Vue 如何更新数组以及为什么有些数组的数据变更不能被 Vue 监测到,对vue监控数组知识是面试比较常见的问题,感兴趣的朋友一起看看吧

  6. Vue子组件props从父组件接收数据并存入data

    这篇文章主要介绍了Vue子组件props从父组件接收数据并存入data的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  7. Vue h函数的使用详解

    本文主要介绍了Vue h函数的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  8. VUE响应式原理的实现详解

    这篇文章主要为大家详细介绍了VUE响应式原理的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  9. vue+Element ui实现照片墙效果

    这篇文章主要为大家详细介绍了vue+Element ui实现照片墙效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. vue+elemet实现表格手动合并行列

    这篇文章主要为大家详细介绍了vue+elemet实现表格手动合并行列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部