博客地址:https://ainyi.com/66

又接到新需求了吧~~

背景

在一个大表单里,有可能会出现这种需求,用户可以自己操作动态添加、移除表单,更加个性化的效果。

常见于填写个人信息、附加内容的表单

例如:

“工作经历”可以用户自己点击继续添加按钮,在原有的表单后面 append 多一个表单,不需要就点击右上方 X 按钮移除

问题

在实现之前,提出几个问题

  1. vue 怎么动态渲染或移除表单上去
  2. v-model 怎么绑定动态添加表单的 value 值
  3. 动态新增的表单如何验证
  4. 动态表单怎么填写对应的 prop

...

好吧,我当时也思考了一会,最后选择数组方式,动态渲染

代码实现讲解

利用数组,v-for 循环方式,可以完美实现动态渲染和移除,因为操作的只有对象数组而已

请格外注意动态添加表单的 rule 和 prop

每个动态添加的表单都要加上 rule

prop 需要根据对象数组下标绑定设置对应的 value(:prop="'azList[' + index + '].azName'")

  1. <div class="section-form" v-for="(item, index) in form.azList" :key="index">
  2. <span v-if="isShowCloseBtn" class="close" @click="deleteItem(index)">
  3. <i class="el-icon-close"></i>
  4. </span>
  5. <el-form-item label="可用区名称:"
  6. :rules="[{ required: true, message: '可用区名称不能为空' }]"
  7. :prop="'azList[' + index + '].azName'"
  8. label-width="150px">
  9. <el-input placeholder="请输入可用区名称" v-model="item.azName" :maxlength="30"></el-input>
  10. </el-form-item>
  11. <el-form-item label="逻辑可用区编码:"
  12. :rules="[{ required: true, message: '逻辑可用区编码不能为空' }]"
  13. label-width="150px"
  14. :prop="'azList[' + index + '].logicCode'">
  15. <el-input placeholder="请输入唯一ID" v-model="item.logicCode" :maxlength="30"></el-input>
  16. </el-form-item>
  17. <el-form-item label="物理可用区编码:"
  18. :rules="[{ required: true, message: '物理可用区编码不能为空' }]"
  19. label-width="150px"
  20. :prop="'azList[' + index + '].physicCode'">
  21. <el-input placeholder="请输入唯一ID" v-model="item.physicCode" :maxlength="30"></el-input>
  22. </el-form-item>
  23. </div>

那么对应的 js 代码为

  1. export default {
  2. name: 'vouchersDetail',
  3. data() {
  4. return {
  5. form: {
  6. regionName: '',
  7. regionCode: '',
  8. // 动态添加的对象数组
  9. azList: [
  10. {
  11. azName: '',
  12. logicCode: '',
  13. physicCode: ''
  14. }
  15. ]
  16. }
  17. }
  18. },
  19. computed: {
  20. // 至少保留一个动态表单的开关
  21. isShowCloseBtn() {
  22. return this.form['azList'].length > 1
  23. }
  24. },
  25. methods: {
  26. addItem() {
  27. // 点击添加表单的按钮,只需要将表单绑定的 value 作为对象 push 到对象数组
  28. this.form['azList'].push({
  29. azName: '',
  30. logicCode: '',
  31. physicCode: '',
  32. weight: ''
  33. })
  34. },
  35. deleteItem(index) {
  36. // 点击移除表单的按钮,根据点击的当前 index 移除对象数组的元素
  37. this.form['azList'].splice(index, 1)
  38. },
  39. goBack() {
  40. window.history.back(-1)
  41. }
  42. }
  43. }

更新

19号更新,分离组件方法,写法更简便,易维护,还可以将校验规则剥离出去

根据上面的方法 利用数组,v-for 循环方式

此次更新,关键在于,是父组件引用子组件的 template 循环

v-for 循环数组的 item 对象传入子组件 template

每个子组件的 form 的 :model = 传入的 item,也就不需要用到数组下标 index,每个子组件是独立的一个 form,也就是说,每个动态添加字段的校验规则可以剥离出去了

父组件

template 循环

  1. <create-region
  2. class="section-form"
  3. ref="refCreateAz"
  4. :infoData="item"
  5. :indexNum="index"
  6. :isShowCloseBtn="isShowCloseBtn"
  7. v-for="(item, index) in form.azList"
  8. :key="index"
  9. @deleteItem="deleteItem">
  10. </create-region>

js 与原来无差,只是多了引入子组件的 component

  1. components: {
  2. CreateRegion: () => import('@/views/region/models/CreateRegion')
  3. }

子组件

  1. <template>
  2. <el-form :model="infoData" :rules="rulesAz" label-width="150px" ref="formAz">
  3. <span v-if="isShowCloseBtn" class="close" @click="deleteItem">
  4. <i class="el-icon-close"></i>
  5. </span>
  6. <el-form-item label="可用区名称:" prop="azName" label-width="150px">
  7. <el-input placeholder="请输入可用区名称" v-model="infoData.azName" :maxlength="30"></el-input>
  8. </el-form-item>
  9. <el-form-item label="逻辑可用区编码:" label-width="150px" prop="logicCode">
  10. <el-input placeholder="请输入唯一ID" v-model="infoData.logicCode" :maxlength="30"></el-input>
  11. </el-form-item>
  12. <el-form-item label="物理可用区编码:" label-width="150px" prop="physicCode">
  13. <el-input placeholder="请输入唯一ID" v-model="infoData.physicCode" :maxlength="30"></el-input>
  14. </el-form-item>
  15. <el-form-item label="权重设置:" label-width="150px">
  16. <el-input placeholder="请设置权重" v-model="infoData.weight"></el-input>
  17. </el-form-item>
  18. </el-form>
  19. </template>
  20. <script>
  21. import { ORGION_AZLIST_RULES } from '@/views/service/rules'
  22. export default {
  23. props: {
  24. infoData: {
  25. require: true
  26. },
  27. indexNum: {
  28. type: Number
  29. },
  30. isShowCloseBtn: {
  31. type: Boolean
  32. }
  33. },
  34. data() {
  35. return {
  36. form: this.infoData,
  37. rulesAz: ORGION_AZLIST_RULES.call(this)
  38. }
  39. },
  40. computed: {},
  41. methods: {
  42. deleteItem() {
  43. this.$emit('deleteItem', this.indexNum)
  44. },
  45. validates() {
  46. return new Promise((resolve, reject) => {
  47. this.$refs['formAz'].validate(async valid => {
  48. if (valid) {
  49. // 验证通过
  50. resolve(true)
  51. } else {
  52. reject(false)
  53. }
  54. })
  55. })
  56. }
  57. }
  58. }
  59. </script>

校验

  1. export const ORGION_AZLIST_RULES = function() {
  2. return {
  3. logicCode: [
  4. {
  5. required: true,
  6. message: '逻辑可用区编码不能为空',
  7. trigger: 'blur'
  8. },
  9. {
  10. validator: CHECK_AZEXITS_CODE.bind(this),
  11. trigger: 'blur'
  12. }
  13. ],
  14. physicCode: [
  15. {
  16. required: true,
  17. message: '物理可用区编码不能为空',
  18. trigger: 'blur'
  19. },
  20. {
  21. validator: CHECK_AZEXITS_CODE.bind(this),
  22. trigger: 'blur'
  23. }
  24. ],
  25. azName: [
  26. {
  27. required: true,
  28. message: '可用区名称不能为空',
  29. trigger: 'blur'
  30. }
  31. ]
  32. }
  33. }

自定义校验

  1. export const CHECK_AZEXITS_CODE = async function(rule, value, callback) {
  2. let paramName = rule.field
  3. let reqData = {}
  4. reqData[paramName] = value
  5. let { result } = await getAzExist(reqData)
  6. if (result.result) {
  7. if (paramName === 'logicCode') {
  8. callback(new Error('逻辑可用区编码已存在,请重新输入'))
  9. } else {
  10. callback(new Error('物理可用区编码已存在,请重新输入'))
  11. }
  12. } else {
  13. callback()
  14. }
  15. }

写在后面

如果大家有啥更好的方法实现,欢迎在评论区相互探讨~

写完下班、

博客地址:https://ainyi.com/66

vue + element 动态渲染、移除表单并添加验证的更多相关文章

  1. v-if案例解析(element-ui form-item 结合 v-if 动态生成rule规则\表单元素,表单无法验证问题剖析 )

    fire 读在最前面: 1.此文章衔接Vue 虚拟Dom 及 部分生命周期初探,相关整体知识点请先阅读后再继续本文阅读 问:当v-if为true时,会重新渲染相关dom节点吗? <child v ...

  2. 如何在.Net Core MVC中为动态表单开启客户端验证

    非Core中的请参照: MVC的验证 jquery.validate.unobtrusive mvc验证jquery.unobtrusive-ajax 参照向动态表单增加验证 页面引入相关JS: &l ...

  3. vue同一页面中拥有两个表单时,验证问题

    问题:如果vue的同一个页面拥有两个表单.验证第一个表单时没有通过就切换到第二个,那么第二个表单会出现验证错误的信息 我们可以通过为两个表单添加ref属性 之后在通过调用resetFields()方法 ...

  4. 使用CSS来渲染HTML的表单元素

    效果: 实现: <!DOCTYPE html> <html> <head> <title>使用CSS来渲染HTML的表单元素</title> ...

  5. Element Ui使用技巧——Form表单的校验规则rules详细说明

    Element UI中对Form表单验证的使用介绍: Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item的 prop 属性设置为需校验的字段名 ...

  6. 第一百八十六节,jQuery,验证表单插件,Ajax 表单插件,验证和提交表单

    jQuery,验证表单插件,Ajax 表单插件,验证和提交表单 HTML <form id="reg" method="post" action=&quo ...

  7. 推荐几款很棒的 JavaScript 表单美化和验证插件

    表单元素让人爱恨交加.作为网页最重要的组成部分,表单几乎无处不在,从简单的邮件订阅.登陆注册到复杂的需要多页填写的信息提交功能,表单都让开发者花费了大量的时间和精力去处理,以期实现好用又漂亮的表单功能 ...

  8. form表单的ajax验证2

    form表单的ajax验证2: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...

  9. 在Tomcat中采用基于表单的安全验证

    .概述   (1)基于表单的验证 基于From的安全认证可以通过TomcatServer对Form表单中所提供的数据进行验证,基于表单的验证使系统开发者可以自定义用户的登陆页面和报错页面.这种验证方法 ...

随机推荐

  1. 【功耗测试环境预置自动化脚本开发】【切换wifi模式为siso模式】【用到方法*args】

    import os,reimport logginglogging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(filename)s[ ...

  2. iscc2018(一只猫的心思)

    由于这一个杂项类没有更新,所以今天特地来写一下博文.希望能够帮助到你们!!!! 其他关于杂项类的解析,可以查看(https://blog.csdn.net/qq_41187256/article/de ...

  3. RabbitMQ和Kafka到底怎么选(二)?

    前言 前一篇文章<RabbitMQ和Kafka到底怎么选?>,我们在吞吐量方面比较了Kafka和RabbitMQ,知道了Kafka的吞吐量要高于RabbitMQ.本文从可靠性方面继续探讨两 ...

  4. Failed to fetch URL http://dl-ssl.google.com/android/repository/addons_list-2.xml, reason:

    http://blog.csdn.net/gyming/article/details/8168166/ 最近接受的这个项目需要Android SDK Tools revision 22.6.2 or ...

  5. 『简单积性函数和dirichlet卷积』

    简单积性函数 在学习欧拉函数的时候,相信读者对积性函数的概念已经有了一定的了解.接下来,我们将相信介绍几种简单的积性函数,以备\(dirichlet\)卷积的运用. 定义 数论函数:在数论上,对于定义 ...

  6. TensorFlow从1到2(七)线性回归模型预测汽车油耗以及训练过程优化

    线性回归模型 "回归"这个词,既是Regression算法的名称,也代表了不同的计算结果.当然结果也是由算法决定的. 不同于前面讲过的多个分类算法或者逻辑回归,线性回归模型的结果是 ...

  7. 结合Mybatis源码看设计模式——外观模式

    定义 提供了一个统一的接口,用来访问子系统中一群接口 适用场景 子系统复杂,增加外观模式提供简单调用接口 构建多层系统结构,用外观对象作为每层入口 详解 外观模式,主要理解外观.通俗一点可以认为这个模 ...

  8. 学习 day4 html 盒子模型

    盒子模型 1.框模型 框:页面上所有元素都可以称为“框” 框模型:(BOX Model),又称盒子模型 定义框处理元素内容.内边距padding.外边距margin.边框的样式border 外边距ma ...

  9. Asp.NetCore轻松学-配置服务 apollo 部署实践

    前言     Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置 ...

  10. Spark初步 从wordcount开始

    Spark初步-从wordcount开始 spark中自带的example,有一个wordcount例子,我们逐步分析wordcount代码,开始我们的spark之旅. 准备工作 把README.md ...