007.表单元素绑定

表单元素绑定

基础用法

你可以用v-model指令在{表单元素}上,创建双向数据绑定。

  • 🔔提示
    1. v-model指令会根据表单元素类型自动选取正确的方法来更新元素。
      • 🪶即v-model指令内部为 ➾ 不同的表单元素使用不同的{属性}并抛出不同的{事件} ➾ 
        1. text和textarea元素使用value属性和input事件。
        2. checkbox和radio元素使用checked属性和change事件。
        3. select元素将value属性作为prop并将change作为事件。
    2. v-model指令会忽略所有表单元素{value、checked、selected属性}的初始值
      • 而总是将 Vue 实例的数据作为数据来源。

1.单行文本框

1
2
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

gif-231130091945

2.多行文本框

1
2
3
4
5
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>

<textarea v-model="message" placeholder="add multiple lines"></textarea>

gif-231130092427

  • 🔔提示
    • 在文本区域插值{<textarea>{{text}}</textarea>}并不会生效,应该使用v-model指令来代替。

3.单选按钮

1
2
3
4
5
6
7
8
9
10
11
<div id="Rbox">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>

<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>

<span>Picked: {{ picked }}</span>
</div>
  • ❗注意
    1. 必须给每一个radio元素,设置一个value属性值。
    2. 单选按钮中,v-model指令必须绑定同一个{数据项} ➾ v-model="picked" ➾ 令单选按钮同组。
  • 🔔提示
    • input id="one" ➾ 对应label for="one"
1
2
3
4
5
6
new Vue({
el: '#Rbox',
data: {
picked: ''
}
})

gif-231130092858

4.复选框

  1. 单个复选框 ➾ 绑定到一个布尔值。

    1
    2
    3
    4
    <div id="Cbox">
    <input type="checkbox" id="checkbox" v-model="checked">
    <label for="checkbox">{{ checked }}</label>
    </div>
    • 🔔提示
      • input id="checkbox" ➾ 对应label for="checkbox"
    1
    2
    3
    4
    5
    6
    new Vue({
    el: '#Cbox',
    data: {
    checked: false
    }
    })

    gif-231130093249

  2. 多个复选框 ➾ 绑定到同一个数组。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <div id="Cbox">
    <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
    <label for="jack">Jack</label>

    <input type="checkbox" id="john" value="John" v-model="checkedNames">
    <label for="john">John</label>

    <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
    <label for="mike">Mike</label>
    <br>

    <span>Checked names: {{ checkedNames }}</span>
    </div>
    • ❗注意
      • 必须给每一个checkbox元素,设置一个value属性值。
      • 📌原因
        • 当勾选时,会将value属性值放入data数组中。
    • 🔔提示
      • input id="jack" ➾ 对应label for="jack"
    1
    2
    3
    4
    5
    6
    new Vue({
    el: '#Cbox',
    data: {
    checkedNames: []
    }
    })

    gif-231130093453

5.菜单

  1. 单选菜单 ➾ 绑定到一个空值。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <div id="Sbox">
    <select v-model="selected">
    <option disabled value="">请选择</option>
    <option>A</option>
    <option>B</option>
    <option>C</option>
    </select>
    <span>Selected: {{ selected }}</span>
    </div>
    1
    2
    3
    4
    5
    6
    new Vue({
    el: '#Sbox',
    data: {
    selected: ''
    }
    })

    gif-231130094059

    • 🔔提示

      • 如果 v-model指令{表达式的初始值}未能匹配任何选项,

      • 那么select元素的状态将被渲染为“未选中”,推荐 ➾ selected: ''

      • 🔥案例

        1. 匹配选项

          1
          2
          3
          4
          5
          6
          new Vue({
          el: '#Sbox',
          data: {
          selected: 'A'
          }
          })

          image-20231130094433908

        2. 不匹配选项

          1
          2
          3
          4
          5
          6
          new Vue({
          el: '#Sbox',
          data: {
          selected: 'a'
          }
          })

          image-20231130094628310

  2. 多选菜单 ➾ 绑定到一个数组。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <div id="Sbox">
    <select v-model="selected" multiple style="width: 50px;">
    <option>A</option>
    <option>B</option>
    <option>C</option>
    </select>
    <br>

    <span>Selected: {{ selected }}</span>
    </div>
    • 🔔提示
      • 不用设置value属性值。
      • 📌原因
        • 默认情况下,<option>内容</option> ➾ value=内容
    1
    2
    3
    4
    5
    6
    new Vue({
    el: '#Sbox',
    data: {
    selected: []
    }
    })

    gif-231130095125

  3. 用 v-for指令动态渲染选项。

    1
    2
    3
    4
    5
    6
    7
    8
    <div id="Sbox">
    <select v-model="selected">
    <option v-for="option in options" v-bind:value="option.value">
    {{ option.text }}
    </option>
    </select>
    <span>Selected: {{ selected }}</span>
    </div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    new Vue({
    el: '#Sbox',
    data: {
    selected: 'A',
    options: [
    { text: 'One', value: 'A' },
    { text: 'Two', value: 'B' },
    { text: 'Three', value: 'C' }
    ]
    }
    })

    gif-231130095435

🔥案例➾ 表单绑定➾ 购物车

  1. 第一部分

    1
    2
    3
    4
    5
    6
    7
    <div id="box">
    <input type="checkbox" v-model="isAll" @change="handleAllChecked" />全选/全不选

    <ul>
    <li v-for="(item, index) in datalist" :key="item.id">
    <input type="checkbox" v-model="checkList" :value="item" @change="handleItemChecked" />
    <img :src="item.pic" />
    1. isAll ➾ 全选/全不选状态。
    2. checkList ➾ 勾选的购物车数据数组。
    image-20231205094104701
    1. data()

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      data() {
      return {
      isAll: false,
      checkList: [], // 勾选的购物车数据数组。

      datalist: [{
      name: "商品1",
      price: 10,
      number: 1,
      id: 1,
      limit: 5, // 限购
      pic: "https://static.maizuo.com/pc/v5/usr/movie/44dc08914d508fc47c8267c6ca73f2d8.jpg"
      },
      {
      name: "商品2",
      price: 20,
      number: 2,
      id: 2,
      limit: 10, // 限购
      pic: "https://static.maizuo.com/pc/v5/usr/movie/44dc08914d508fc47c8267c6ca73f2d8.jpg"
      },
      {
      name: "商品3",
      price: 30,
      number: 3,
      id: 3,
      limit: 15, // 限购
      pic: "https://static.maizuo.com/pc/v5/usr/movie/44dc08914d508fc47c8267c6ca73f2d8.jpg"
      }]
      }
      }
    2. methods()

      1. handleAllChecked() ➾ 全选/全不选。

        1
        2
        3
        4
        5
        6
        7
        handleAllChecked() {
        if (this.isAll) {
        this.checkList = this.datalist
        } else {
        this.checkList = []
        }
        }
        • 🔔提示
          • this.isAll ➾ this.checkList = this.datalist
            • 全选 ➾ 勾选的数据 = 原来的数据。
      2. handleItemChecked() ➾ 每项选择。

        1
        2
        3
        4
        5
        6
        7
        handleItemChecked() {
        if (this.checkList.length === this.datalist.length) {
        this.isAll = true
        } else {
        this.isAll = false
        }
        }
        • 🔔提示
          • this.isAll = true
            • 勾选的数据的长度 = 原来的数据的长度 ➾ 全选。
  2. 第二部分

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        <div>
    <span>{{ item.name }}: </span>
    <span style="color:red;">¥{{ item.price }}</>
    </div>
    <div>

    <button @click="item.number--" :disabled="item.number===1">-</button>
    <span>{{item.number}}</span>
    <button @click="item.number++" :disabled="item.number===item.limit">+</button>
    </div>
    <div>
    <button @click="handleDeleteClick(index, item.id)">删除</button>
    </div>
    </li>
    </ul>
    1. :disabled="item.number===1"
      • 最小购买数 ➾ 1。
    2. :disabled="item.number===item.limit"
      • 最大购买数 ➾ item.limit。
    image-20231205094238874
    1. data()

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      data() {
      return {
      isAll: false,
      checkList: [], // 勾选的购物车数据数组。

      datalist: [{
      name: "商品1",
      price: 10,
      number: 1,
      id: 1,
      limit: 5, // 限购
      pic: "https://static.maizuo.com/pc/v5/usr/movie/44dc08914d508fc47c8267c6ca73f2d8.jpg"
      },
      {
      name: "商品2",
      price: 20,
      number: 2,
      id: 2,
      limit: 10, // 限购
      pic: "https://static.maizuo.com/pc/v5/usr/movie/44dc08914d508fc47c8267c6ca73f2d8.jpg"
      },
      {
      name: "商品3",
      price: 30,
      number: 3,
      id: 3,
      limit: 15, // 限购
      pic: "https://static.maizuo.com/pc/v5/usr/movie/44dc08914d508fc47c8267c6ca73f2d8.jpg"
      }]
      }
      }
    2. methods()

      1. handleDeleteClick(index, item.id) ➾ 删除商品。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        handleDeleteClick(index, id) {

        // 依赖index➾ 删除datalist
        this.datalist.splice(index, 1)

        // 依赖id➾ 删除checklist
        this.checkList = this.checkList.filter(item => item.id !== id)

        // 状态同步
        this.handleItemChecked()
        }
      2. handleItemChecked() ➾ 每项选择。

        1
        2
        3
        4
        5
        6
        7
        handleItemChecked() {
        if (this.checkList.length === this.datalist.length) {
        this.isAll = true
        } else {
        this.isAll = false
        }
        }
  3. 第三部分

    1
    2
    3
    4
      <div>总金额: {{ sum() }}</div>

    {{checkList}}
    </div>
    • checkList ➾ 勾选的购物车数据数组。

    image-20231205094346834

    • methods()

      • sum() ➾ 累加计算 checkList 数组的每一项的价格×数量

        1
        2
        3
        4
        5
        6
        7
        8
        9
        sum() {
        var total = 0

        this.checkList.forEach(item => {
        total += item.price * item.number
        })

        return total
        }
    gif-231205102111

值绑定

对于单选按钮、复选框及菜单,v-model指令绑定的值通常是 ➾ 静态字符串{对于复选框也可以是布尔值}。

1.单选按钮

1
<input type="radio" v-model="pick" v-bind:value="a" />
  • 当选中时 ➾ 
    • vm.pick === vm.a

2.复选框

1
2
3
4
5
6
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
  1. toggle 为 true false。
  2. 当选中时 ➾ 
    • vm.toggle === 'yes'
  3. 当没有选中时 ➾ 
    • vm.toggle === 'no'
  4. 这里的 true-value属性false-value属性
    • 并不会影响表单元素的 value属性
    • 📌原因
      • 浏览器在提交表单时,并不会包含 ➾ 未被选中的复选框。

3.菜单

1
2
3
4
<select v-model="selected">
<!-- 内联对象字面量 -->
<option :value="{ number: 123 }">123</option>
</select>
  • 当被选中时 ➾ 
    1. vm.selected ➾ { number: 123 }
    2. vm.selected.number ➾ 123

表单修饰符

  1. .lazy

    • 用于将v-model指令中使用的input事件切换为change事件 ➾ 

      • 当用户输入完成后再对数据 ➾ 进行处理。
    • 语法

      1
      <input v-model.lazy="msg">
    • 🔥案例

      1. v-model="msg"

        1
        2
        3
        <div id="box">
        <input v-model="myName" />我的姓名: {{myName}}
        </div>

        gif-231206101252

      2. v-model.lazy="msg"

        1
        2
        3
        <div id="box">
        <input v-model.lazy="myName" />我的姓名: {{myName}}
        </div>

        gif-231206101211

  2. .number

    • 用于自动将用户输入的值转为 ➾ 数值类型。

      • 🔔提示
        • 即便在type='number' 时,HTML表单的值也总会返回 ➾ 字符串{string}。
    • 语法

      1
      <input v-model.number="msg">
    • 🔥案例

      1. v-model="msg"

        1
        2
        3
        <div id="box">
        <input v-model="myAge" />我的年龄: {{myAge}}
        </div>
        gif-231206102030
      2. v-model.number="msg"

        1
        2
        3
        <div id="box">
        <input v-model.number="myAge" />我的年龄: {{myAge}}
        </div>
        gif-231206102123
  3. .trim

    • 用于自动过滤用户输入的 ➾ 首尾空白字符。

    • 语法

      1
      <input v-model.trim="msg">
    • 🔥案例

      1. v-model="msg"

        1
        2
        3
        <div id="box">
        <input v-model="myHappy" />我的爱好的长度是: {{myHappy.length}}
        </div>

        gif-231206102721

      2. v-model.trim="msg"

        1
        2
        3
        <div id="box">
        <input v-model.trim="myHappy" />我的爱好的长度是: {{myHappy.length}}
        </div>

        gif-231206102632