Skip to content

表单处理

表单元素的数据绑定

下面是一个文本框和数据进行绑定的例子:

vue
<template>
  <input
    type="text"
    :value="textContent"
    @input="(e) => (textContent = e.target.value)"
  />
  <p>你当前输入的内容为:{{ textContent }}</p>
</template>

<script setup>
import { ref } from "vue";
const textContent = ref("");
</script>

<style scoped></style>

上面的例子我们让文本库和 ref 数据进行了绑定,用户在输入内容的时候,会去更新 textContent 这个 ref 数据,而 ref 数据的变化又会影响文本框本身的 value 值。这其实就是一个双向绑定的例子。

v-model

上面的例子虽然实现了双向绑定,但是写起来比较麻烦,因此 Vue 提供了一个内置的指令 v-model

vue
<template>
  <input type="text" v-model="textContent" />
  <p>你当前输入的内容为:{{ textContent }}</p>
</template>

<script setup>
import { ref } from "vue";
const textContent = ref("");
</script>

<style scoped></style>

上面的例子使用了 v-model 来进行双向绑定,textContent 的变化会影响文本框的值,文本框的值也会影响 textContent.

使用 v-model 的好处在于:

  1. 简化了书写
  2. 根据所使用的元素自动的选择对应的属性以及事件组合
    • input 或者 textarea,元素会绑定 input 事件,绑定的值是 value
    • 如果是单选框或者复选框,背后绑定的事件是 change 事件,绑定的值 checked
    • select 下拉列表绑定的也是 change 事件,绑定的值是 value

文本域

文本域就是多行文本,对应的标签为 textarea

vue
<template>
  <textarea cols="30" rows="10" v-model="textContent"></textarea>
  <p>你当前输入的内容为:{{ textContent }}</p>
</template>

<script setup>
import { ref } from "vue";
const textContent = ref("");
</script>

<style scoped></style>

复选框

单一的复选框,可以使用 v-model 去绑定一个 ref 类型的布尔值,布尔值为 true 表示选择中,false 表示未选中

vue
<template>
  <input type="checkbox" v-model="checked" />
  <button @click="checked = !checked">切换选中</button>
</template>

<script setup>
import { ref } from "vue";
const checked = ref(true);
</script>

<style scoped></style>

在上面的例子中,布尔值 true 是选中,false 是未选中,但是这个真假值是可以自定义:

vue
<template>
  <input
    type="checkbox"
    v-model="checked"
    :true-value="customTrue"
    :false-value="customFalse"
  />
  <button @click="toggle">切换选中</button>
</template>

<script setup>
import { ref } from "vue";
const checked = ref("yes");
// 现在相当于是自定义什么值是选中,什么值是未选中
// 之前是默认true是选中,false是未选中
// 现在是yes是选中,no是未选中
const customTrue = ref("yes");
const customFalse = ref("no");
function toggle() {
  checked.value === "yes" ? (checked.value = "no") : (checked.value = "yes");
}
</script>

<style scoped></style>

有些时候我们有多个复选框,这个时候,可以将多个复选框绑定到同一个数组或者集合的值:

vue
<template>
  <div v-for="(item, index) in arr" :key="index">
    <label for="item.id">{{ item.title }}</label>
    <input type="checkbox" v-model="hobby" :id="item.id" :value="item.value" />
  </div>
  <p>{{ message }}</p>
</template>

<script setup>
import { ref, computed } from "vue";
const hobby = ref([]);
const arr = ref([
  { id: "swim", title: "游泳", value: "游个泳" },
  { id: "run", title: "跑步", value: "跑个步" },
  { id: "game", title: "游戏", value: "玩个游戏" },
  { id: "music", title: "音乐", value: "听个音乐" },
  { id: "movie", title: "电影", value: "看个电影" },
]);
const message = computed(() => {
  // 根据 hobby 的值进行二次计算
  if (hobby.value.length === 0) return "请选择爱好";
  else return `您选择了${hobby.value.join("、")}`;
});
</script>

<style scoped></style>

在上面的例子中,checkbox 所绑定的数据不再是一个布尔值,而是一个数组(集合),那么当该复选框被选中的时候,该复选框所对应的值就会被加入到数组里面。

单选框

vue
<template>
  <label for="male">男</label>
  <input type="radio" id="male" v-model="gender" value="男" />
  <label for="female">女</label>
  <input type="radio" id="female" v-model="gender" value="女" />
  <label for="secret">保密</label>
  <input type="radio" id="secret" v-model="gender" value="保密" />
</template>

<script setup>
import { ref } from "vue";
const gender = ref("保密");
setTimeout(() => {
  gender.value = "男";
}, 3000);
</script>

<style scoped></style>

上面的例子演示了单选框如何进行双向绑定,哪一个单选框被选中取决于 gender 的值。

下拉列表

下拉列表在进行双向绑定的时候,v-model 是写在 select 标签上面:

vue
<template>
  <!-- 下拉列表列表是单选的话,v-model 绑定的值是一个字符串,这个字符串是 option 的 value 值 -->
  <select v-model="hometown1">
    <option value="" disabled>请选择</option>
    <option
      v-for="(item, index) in hometownList"
      :key="index"
      :value="item.key"
    >
      {{ item.value }}
    </option>
  </select>
  <p>您选择的家乡为:{{ hometown1 }}</p>
  <!-- 如果下拉列表是多选的话,v-model 绑定的值是一个数组,这个数组是 option 的 value 值组成的数组 -->
  <select v-model="hometown2" multiple>
    <option value="" disabled>请选择</option>
    <option
      v-for="(item, index) in hometownList"
      :key="index"
      :value="item.key"
    >
      {{ item.value }}
    </option>
  </select>
  <p>您选择的家乡为:{{ hometown2 }}</p>
</template>

<script setup>
import { ref } from "vue";
const hometown1 = ref("");
const hometown2 = ref([]);
const hometownList = ref([
  { key: "成都", value: "成都" },
  { key: "帝都", value: "北京" },
  { key: "魔都", value: "上海" },
  { key: "妖都", value: "广州" },
  { key: "陪都", value: "重庆" },
]);
</script>

<style scoped></style>

注意下拉列表根据是单选还是多选,v-model 所绑定的值的类型不一样,单选绑定字符串,多选绑定数组。

v-model 表单修饰符

  • lazy:默认情况下,v-model 会在每次 input 事件触发时就更新数据,lazy 修饰符可以改为 change 事件触发后才更新数据
  • number:将用户输入的内容从字符串转为 number 类型
  • trim:去除输入的内容的两端的空格
vue
<template>
  <!-- lazy修饰符演示 -->
  <input type="text" v-model.lazy="mess1" />
  <p>你输入的是:{{ mess1 }}</p>
  <p>类型为{{ typeof mess1 }}</p>
  <p>长度为{{ mess1.length }}</p>

  <!-- number修饰符演示 -->
  <input type="text" v-model.number="mess2" />
  <p>你输入的是:{{ mess2 }}</p>
  <p>类型为{{ typeof mess2 }}</p>
  <p>长度为{{ mess2.length }}</p>

  <!-- trim修饰符演示 -->
  <input type="text" v-model.trim="mess3" />
  <p>你输入的是:{{ mess3 }}</p>
  <p>类型为{{ typeof mess3 }}</p>
  <p>长度为{{ mess3.length }}</p>
</template>

<script setup>
import { ref } from "vue";
const mess1 = ref("");
const mess2 = ref("");
const mess3 = ref("");
</script>

<style scoped></style>

-EOF-

MIT License