Vue 中实现动态增减输入框 / 选择器等表单输入元素

前言

在做前端开发过程中,我们经常会遇到这样的需求:要求动态增减输入框、下拉选择等输入元素(如下图)。

如果是Vue新手的话可能会疑惑:“我一个 input 输入框或者 select 下拉选择只能绑定一个 v-model,如果动态增减,我们都不知道总共有多少个或者多少组输入元素,我们应该如何处理动态的 v-model 呢?”

解决思路

使用数组作为状态数据,然后把单个 / 或者单组输入元素封装为 Vue 子组件。面对这种动态增减输入元素的处理方式一般我们是化繁为简。单个 / 单组输入元素封装为单个 Vue 组件后,在组件里面我们就可以愉快地给每个元素定义一个 v-model 来处理了,我们还可以给组件外暴露属性 props 和事件 events 供外部调用。动态增减的处理也相对简单,就维护一个数组,数组里面每条数据对应一个上面定义的 Vue 组件;这样,对数组进行增删改,直接更新到组件视图

组件实现代码

这里以一个简单的 elementUI 输入框为例

<template>
  <div class="panel__item clearfix">
    <div class="left panel__label">
      {{ label }}
    </div>
    <div
      :class="{'last': isLastItem}"
      class="right panel__input"
    >
      <el-input
        v-model="value"
        size="small"
        placeholder="请填写"
        @change="change"
      />
      <el-button
        v-if="isLastItem"
        type="primary"
        size="small"
        @click="deleteItem"
      >一</el-button>
      <div
        v-if="isLastItem"
        class="add-item"
        @click="addItem"
      >
        <el-button
          type="primary"
          size="small"
        >十</el-button><span class="add-item__desc">添加输入框</span>
      </div>
    </div>
  </div>
</template>
export default {
  props: {
    defaultValue: {
      type: Object,
      default: () => {
        return {
          label: '',
          value: '',
          isLastItem: false
        }
      }
    }
  },
  data () {
    return {
      value: '',
      label: '',
      isLastItem: ''
    }
  },
  created () {
    this.value = this.defaultValue.value
    this.label = this.defaultValue.label
    this.isLastItem = this.defaultValue.isLastItem
  },
  methods: {
    change (value) {
      this.$emit('change', value)
    },
    deleteItem () {
      this.$emit('deleteItem', this.label, this.value)
    },
    addItem () {
      this.$emit('addItem')
    }
  }
}

外部调用方式

外部调用方式要注意传参的方式的处理,代码如下:

<my-input
            v-for="(item, index) in items"
            :key="index"
            :default-value="{ label : item.label, value : item.value }"
            @change="(label, val) => inputChange(label, val, index)"
            @addItem="addItem"
            @deleteItem="() => deleteItem(index)"
          />
  methods: {
    inputChange (val, index) {
      // 相应改变items数组对应index元素的数据
    },
    addItem () {
      // 相应改变items数组,push一个元素
    },
    deleteItem (index) {
      // 相应删除items数组对应index元素的数据
    }
  }

扩展

上面只是一个最简单的动态增减元素 / 组件的处理方式,如果要动态增加的组件里面需要再嵌套动态增减元素 / 组件呢?如法炮制!

还是一样的处理方式,定义好最小粒度的一个或者一组元素使用 v-model 绑定好的一个 Vue 组件,然后往上就是处理多维数组的操作(对数组元素进行增删改查而已)。

作者: 博主

Talk is cheap, show me the code!

发表评论

邮箱地址不会被公开。

Captcha Code