• vue动态表单DynamicForm 吴小明


    效果:

      

    预期:像这样的表单结构,如果在form中一行一行写每个文本域,有点麻烦,封装成一个组件,同类型支持新增和删除

      ①DynamicForm.vue

    <template>
      <div class="dynamic-form">
        <div class="title">
          <p>{{template.title}}</p>
          <van-icon name="add-o" @click="handleAdd" />
        </div>
        <div class="content" v-for="(item,index) in MyList" :key="index">
          <p class="icon" @click="handleDelete(index)">
            <img src="@/assets/public/delete.svg">
          </p>
          <van-field v-for="(ele,i) in template.labels" :key="i" v-model="item[ele.field]" rows="3" autosize :label="ele.name" placeholder="请输入" type="textarea" maxlength="200"
            show-word-limit clearable required :rules="[{required:true,message:'必填项,不能为空'}]" />
        </div>
      </div>
    </template>
    <script>
    export default {
      model: { prop: 'data', event: 'change' },
      computed: {
        MyList: {
          get: vm => vm.data,
          set(data) {
            this.$emit('change', data)
          }
        }
      },
      props: {
        template: { type: Object, required: true },
        data: { type: Array, require: true }
      },
      methods: {
        handleAdd() {
          this.MyList.push({})
        },
        handleDelete(index) {
          if (this.MyList.length === 1) return this.$toast('必须保留一项')
          this.MyList.splice(index, 1)
        }
      }
    }
    </script>
    <style lang="less" scoped>
    .dynamic-form {
      & + & {
        margin-top: 20px;
      }
      .title {
        display: flex;
        justify-content: space-between;
        align-items: center;
        position: relative;
        > p {
          margin-left: 15px;
          font-size: 16px;
          color: #4d5c82;
        }
        .van-icon {
          color: #198cff;
          font-size: 20px;
          font-weight: 600;
        }
        .van-icon::after {
          content: '';
          position: absolute;
          top: -5px;
          bottom: -5px;
          left: -5px;
          right: -5px;
          border-radius: 50%;
        }
        &::before {
          content: '*';
          position: absolute;
          color: #fc5e5e;
        }
      }
      /deep/ .content {
        margin-top: 10px;
        background-color: #f0f4f8;
        border-radius: 5px;
        padding: 15px;
        position: relative;
        > .icon {
          position: absolute;
          right: 15px;
          top: 10px;
          z-index: 10;
        }
        > .icon::after {
          content: '';
          position: absolute;
          top: -5px;
          bottom: -5px;
          left: -5px;
          right: -5px;
          border-radius: 50%;
        }
        .van-cell--required::before {
          color: #fc5e5e;
          left: 0;
        }
        .van-cell::after {
          border-bottom: none;
        }
        .van-cell {
          padding: 0;
          line-height: 1;
          align-items: center;
          margin-top: 20px;
          display: block;
          background-color: #f0f4f8;
          &:first-of-type {
            margin-top: 0;
          }
          .van-field__label {
            margin-left: 15px;
            width: 90%;
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
            word-break: break-all;
            > span {
              font-size: 16px;
              color: #4d5c82;
            }
          }
          .van-field__value {
            margin-top: 10px;
            padding-left: 8px;
            padding-right: 8px;
            line-height: 32px;
            background-color: #fff;
            border-radius: 5px;
            input::-webkit-input-placeholder,
            textarea::-webkit-input-placeholder {
              color: rgba(#4d5c82, 0.6);
            }
            .van-field__control {
              color: #4d5c82;
              font-size: 16px;
            }
            .van-field__word-limit {
              position: absolute;
              right: 5px;
              bottom: 5px;
              color: rgba(#4d5c82, 0.6);
              font-size: 12px;
            }
          }
        }
      }
    }
    </style>
    View Code

      ②拜访计划中使用

        // 引入
        import DynamicForm from '@/components/DynamicForm'
    
        // data
          page2Data: [
            {
              title: '拜访计划',
              variable: 'requirements',
              labels: [
                { name: '初步预测需求点', field: 'requirement' },
                { name: '判断理由', field: 'reason' }
              ],
              data: [{}]
            },
            {
              title: '提问设计(我方提问)',
              variable: 'questions',
              labels: [{ name: '问题', field: 'question' }],
              data: [{}]
            },
            {
              title: '杜宾清单(客户会提的问题或者顾虑)',
              variable: 'duBins',
              labels: [
                { name: '问题', field: 'question' },
                { name: '解决方案', field: 'solution' }
              ],
              data: [{}]
            },
            {
              title: '信任等级',
              variable: 'trustLevels',
              labels: [
                { name: '提升计划', field: 'improvementPlan' },
                { name: '原因', field: 'reason' }
              ],
              data: [{}]
            },
            {
              title: '物料准备',
              variable: 'materials',
              labels: [
                { name: '具体物料', field: 'material' },
                { name: '选择原因', field: 'reason' }
              ],
              data: [{}]
            }
          ]

      DOM:

        <van-form @submit="handleSubmit" validate-trigger='onSubmit'>
          <DynamicForm v-for="(item,index) in page2Data" :key="index" v-model="item.data" :template='item' />
          <div class="page2-footer">
            <van-button native-type="submit" :loading='submitLoading'>提交</van-button>
          </div>
        </van-form>

      得到的数据结构:

          const arr = [
            {
              title: '拜访计划',
              variable: 'requirements',
              labels: [
                { name: '初步预测需求点', field: 'requirement' },
                { name: '判断理由', field: 'reason' }
              ],
              data: [{ requirement: '2', reason: '2' }]
            },
            {
              title: '提问设计(我方提问)',
              variable: 'questions',
              labels: [{ name: '问题', field: 'question' }],
              data: [{ question: '1' }]
            },
            {
              title: '杜宾清单(客户会提的问题或者顾虑)',
              variable: 'duBins',
              labels: [
                { name: '问题', field: 'question' },
                { name: '解决方案', field: 'solution' }
              ],
              data: [{ question: '1', solution: '1' }]
            },
            {
              title: '信任等级',
              variable: 'trustLevels',
              labels: [
                { name: '提升计划', field: 'improvementPlan' },
                { name: '原因', field: 'reason' }
              ],
              data: [{ improvementPlan: '6', reason: '6' }]
            },
            {
              title: '物料准备',
              variable: 'materials',
              labels: [
                { name: '具体物料', field: 'material' },
                { name: '选择原因', field: 'reason' }
              ],
              data: [{ material: '16', reason: '6' }]
            }
          ]
    View Code

      ③拜访反馈中使用

        // 引入
        import DynamicForm from '@/components/DynamicForm'
    
        // data
          page2Data: [
            {
              title: '需求调研结果汇总',
              variable: 'requirementList',
              labels: [
                { name: '客户实际需求', field: 'requirement' },
                { name: '判断理由', field: 'reason' }
              ],
              data: [{}]
            },
            {
              title: '客户实际提出的顾虑/问题',
              variable: 'questionList',
              labels: [{ name: '顾虑/问题', field: 'concern' }],
              data: [{}]
            }
          ]

      DOM:

        <van-form @submit="handleSubmit" validate-trigger='onSubmit'>
          <DynamicForm v-for="(item,index) in page2Data" :key="index" v-model="item.data" :template='item' />
          <div class="page2-footer">
            <van-button native-type="submit" :loading='submitLoading'>提交</van-button>
          </div>
        </van-form>

      得到的数据结构:

          const arr = [
            {
              title: '需求调研结果汇总',
              variable: 'requirementList',
              labels: [
                { name: '客户实际需求', field: 'requirement' },
                { name: '判断理由', field: 'reason' }
              ],
              data: [
                { requirement: '1', reason: '2' },
                { requirement: '11', reason: '22' }
              ]
            },
            {
              title: '客户实际提出的顾虑/问题',
              variable: 'questionList',
              labels: [{ name: '顾虑/问题', field: 'concern' }],
              data: [{ concern: '1' }]
            }
          ]
    View Code
  • 相关阅读:
    MYSQL 优化(二),持续更新收藏
    一些linux命令 备份下
    lsyncd +xinetd+syncd 多服务器文件同步
    阿里slb+ecs+https
    微擎 从 php5 到php7 的各种填坑 持续更新
    lmap
    微擎的ifp ife ifpp
    工具索引 mark名字
    Funny Bug || Sky Hole
    mysql 查询小技巧
  • 原文地址:https://www.cnblogs.com/wuqilang/p/16027054.html
Copyright © 2020-2023  润新知