vue2之收集表单数据

226 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

前面我们介绍过,v-model指令主要用于表单元素。今天我们就来介绍一下不同类型表单元素(原生表单元素)是如何使用v-model进行绑定的。

表单元素收集

下面我们以一个例子为例,先写一个form表单。代码如下:

<template>
  <div class="hello">
    <form>
      <div>
        账号:<input type="text" v-model="form.account" />
      </div>
      <div>
        密码:<input type="text" v-model="form.password" />
      </div>
      <div>
        性别:
        男:<input type="radio" v-model="form.gender" />
        女:<input type="radio" v-model="form.gender" />
      </div>
      <div>
        爱好:
        爬山:<input type="checkbox" v-model="form.hobby" />
        拍照:<input type="checkbox" v-model="form.hobby" />
        画画:<input type="checkbox" v-model="form.hobby" />
      </div>
      <div>
        地区:
        <select v-model="form.city">
          <option value="beijing">北京</option>
          <option value="shanghai">上海</option>
          <option value="guangzhou">广州</option>
          <option value="shenzhen">深圳</option>
        </select>
      </div>
      <div>
        其他信息:<textarea v-model="form.other"></textarea>
      </div>
      <div>
        <input type="checkbox" v-model="form.agree" />同意服务协议
      </div>
      <div>
        <button @click="submit">提交</button>
      </div>
    </form>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      form: {}
    }
  },
  methods: {
    submit () {
      console.log('表单数据', this.form)
    }
  }
}
</script>

v-model在内部为不同的输入元素使用不同的property并抛出不同的事件。

下面我们来看一下每一部分是怎么绑定的。

1. 输入框

下面我们看看账号密码这类的输入框是如何绑定的。

<div>
  账号:<input type="text" v-model="form.account" />
</div>
<div>
  密码:<input type="text" v-model="form.password" />
</div>

当我们在输入框中输入内容时,v-model会将我们的输入值绑定到data上。 此时v-model相当于是v-bind:value,而我们输入框的value当用户输入完会自动绑定到value上,无需手动给标签添加value属性。

效果如下:

image.png

2. 单选框Radio

对于单元框这类元素来说,v-model绑定的checked选项对应的value,如果不设置value的话,v-model绑定的将会是个null。

<div>
  性别:
  男:<input type="radio" v-model="form.gender" />
  女:<input type="radio" v-model="form.gender" />
</div>

而且,不绑定value的话,选中其中一个最终所有的都会选中,达不到我们想要的单选效果。

效果如图所示:

image.png

添加value

<div>
  性别:
  男:<input type="radio" value="man" v-model="form.gender" />
  女:<input type="radio" value="woman" v-model="form.gender" />
</div>

此时就能正常绑定data的值了,而且单选效果也能正常交互。

效果如下:

image.png

3. 复选框checkbox

复选框绑定的是checked选项

<div>
  <input type="checkbox" v-model="form.agree" />同意服务协议
</div>

如果checbox是单选的时候,那么绑定的就是对应的checked

效果如下: image.png

<div>
  爱好:
  爬山:<input type="checkbox" v-model="form.hobby" />
  拍照:<input type="checkbox" v-model="form.hobby" />
  画画:<input type="checkbox" v-model="form.hobby" />
</div>

如果checkbox是多选的时候,那么绑定的就是一个数组,内容是对应checked选中状态的value,也就是说多选状态下,必须定义value,如果不定义就是下面的效果:

image.png 所有的都选中,数据绑定失败

多选时候绑定value

<div>
  爱好:
  爬山:<input type="checkbox" value="climb" v-model="form.hobby" />
  拍照:<input type="checkbox" value="photo" v-model="form.hobby" />
  画画:<input type="checkbox" value="paint" v-model="form.hobby" />
</div>
data () {
  return {
    form: {
      hobby: []
    }
  }
},

效果如下:

image.png

需要注意的是:多选绑定的时候一定要设置v-model的那个值为数组,否则它会默认绑定check的值

4. 下拉框select

下拉框也分为单选和多选两种情况。

4.1 单选

不设置value

<div>
  地区:
  <select v-model="form.city">
    <option>北京</option>
    <option>上海</option>
    <option>广州</option>
    <option>深圳</option>
  </select>
</div>

此时绑定的是option里面的内容

效果如下:

image.png

设置value属性

<div>
  地区:
  <select v-model="form.city">
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
    <option value="guangzhou">广州</option>
    <option value="shenzhen">深圳</option>
  </select>
</div>

此时绑定的是option中设置的value属性。

效果如下:

image.png

4.2 多选

不设置value属性

<div>
  地区:
  <select v-model="form.city" multiple>
    <option>北京</option>
    <option>上海</option>
    <option>广州</option>
    <option>深圳</option>
  </select>
</div>

多选和单选的情况相同,绑定的是option里面的内容,只是多选是一个数组,而单选是一个字符串。

效果如下:

image.png

设置value属性

<div>
  地区:
  <select v-model="form.city" multiple>
    <option value="beijing">北京</option>
    <option value="shanghai">上海</option>
    <option value="guangzhou">广州</option>
    <option value="shenzhen">深圳</option>
  </select>
</div>

此时绑定的是一个数组,包含option中设置的value属性。

效果如下:

image.png

5. 多行文本输入框tetxarea

多行文本输入和普通input文本输入一样,都是绑定的value.

<div>
  其他信息:<textarea v-model="form.other"></textarea>
</div>

效果如下:

image.png

小结:

v-model在内部为不同的输入元素使用不同的property并抛出不同的事件:

  • text和textarea元素使用value property和input事件
  • checkbox和radio使用checkbox property和change事件
  • select字段将value作为prop并将change作为事件

具体总结下来:

若:<input type="text" />,则v-model收集的是value值,用户输入的就是value值

若:<input type="radio" />,则v-model收集的是value值,且要给标签设置value属性

若:<input type="checbox" />

  1. 没有设置input的value值,那么v-model收集的就是checked(布尔值,是否选中值)
  2. 设置input的value值,也分为两种情况: - v-model的初始值是非数组,那么收集的就是checked(布尔值,是否选中值) - v-model的初始值是数组,那么收集的就是value组成的数组

修饰符

之前我们介绍过事件是有修饰符的,其实v-model也是有修饰符的,一共有三种修饰符:.number, .lazy, .trim。

1. number修饰符

number修饰符能将字符串转成有效的数字,说到这个不得不提一下input的number类型,它们看起来功能相等,那到底有没有什么区别呢?

1.1 input的number类型

<div>
  密码:<input type="number" v-model="form.password" />
</div>

这种情况下会限制非数字的输入,但是v-model绑定的值还是字符串类型

效果如下: image.png

但是需要注意一下,科学计数符号E(e)是可以输入的,只是绑定的值变成”“, 效果如下:

image.png

1.2 number修饰符

<div>
  密码:<input type="text" v-model.number="form.password" />
</div>

这种情况下,如果输入值包含数值,那么v-model绑定的就是number类型,而且会将字符串转成有效数值。如图所示。

image.png

如果输入不包含数值的字符串,那么v-model绑定的还是字符串类型,不会限制非数值的输入, 如图所示。

image.png

image.png

综上所述,一般会将input的number类型和number修饰符一起使用。

2. lazy修饰符

lazy修饰符可以让v-model在失去焦点之后再收集数据。从上面的例子可以看出,

  • input输入框是在input时就开始收集数据
  • radio和checkbox是在change时开始收集数据
  • select也是在change时开始收集数据

如果在有的业务场景下,需要延迟再收集数据,那么就可以使用lazy修饰符

<div>
  账号:<input type="text" v-model.lazy="form.account" />
</div>

这时候,只有在鼠标失去焦点之后,才会收集数据,data里面的数据才会发生变化

3. trim修饰符

trim修饰符是用来过滤字符串收尾的空格的。

<div>
  账号:<input type="text" v-model="form.account" />
</div>

这种情况下,一旦输入空格,是会收集进去的,如图所示:

image.png

加上trim修饰符之后,收集的数据就会自动被过滤出去。

<div>
  账号:<input type="text" v-model.trim="form.account" />
</div>

效果如下:

image.png