欢迎大家订阅【Vue2+Vue3】入门到实践 专栏,开启你的 Vue 学习之旅!
文章目录
- 1 v-model原理
- 2 表单类组件封装
- 3 v-model简化代码
1 v-model原理
1. 基本原理
v-model
本质上是一个语法糖,它将 value
属性 和 input
事件 的绑定合并为一个指令。
对于输入框这种常见的表单元素,v-model
会自动为你绑定 value
属性和 input
事件,实现数据双向绑定。
2. 作用
提供数据的双向绑定
:value
:数据变,视图跟着变@input
:视图变,数据跟着变
【示例】
<template>
<div id="app" ><input v-model="msg1" type="text"><input :value="msg2" type="text">
</div>
</template><script>
export default {data(){return{msg1:'',msg2:''}}}
</script><style></style>
【详解】
①v-model="msg1"
:msg1
会和第一个 <input>
元素的 value
进行双向绑定。
- 当用户在输入框中输入内容时,
msg1
会更新为输入的值。 - 如果
msg1
改变,输入框的值会同步更新。
②:value="msg2"
:第二个 <input>
通过 :value
绑定 msg2
,但是它并没有绑定 input
事件。
msg2
只是将初始值传递给输入框,但当用户输入新的内容时,msg2
的值不会更新。- 如果希望
msg2
随着用户输入动态更新,还需要显式地处理输入事件。
【运行结果】
【优化】
<template>
<div id="app" ><input v-model="msg1" type="text"><!-- 模板中获取事件的形参 -> 通过 $event 获取 --><input :value="msg2" @input="msg2 = $event.target.value" type="text">
</div>
</template>
:value="msg2" @input="msg2 = $event.target.value"
:第二个 <input>
不仅绑定了 msg2
的初始值(通过 :value="msg2"
),还显式地绑定了 input
事件。
- 每当用户输入时,
@input
事件会触发,并通过$event.target.value
获取输入框的值。 - 通过
msg2 = $event.target.value
,更新msg2
的值,从而实现双向绑定。 - 该方式使得
msg2
的值能够随着用户的输入动态更新。
【运行结果】
3. 注意事项
v-model
在不同类型的表单元素上工作时,底层的实现机制会有所不同。
- 文本框 (
<input type="text">
):绑定value
属性和input
事件。 - 复选框 (
<input type="checkbox">
):绑定checked
属性和change
事件,处理布尔值或数组。 - 单选框 (
<input type="radio">
):绑定checked
属性和change
事件,处理选中的值。 - 下拉框 (
<select>
):绑定value
属性和change
事件,处理选中的值。
Vue 会根据表单元素的不同,自动选择合适的属性和事件来实现数据的双向绑定,从而简化了开发者的工作。
2 表单类组件封装
1. 需求目标
实现子组件和父组件数据的双向绑定 。
2. 示例代码
父组件App.vue
<template><div class="app"><BaseSelect></BaseSelect></div>
</template><script>
import BaseSelect from './components/BaseSelect.vue'
export default {data() {return {selectId: '102',}},components: {BaseSelect,},
}
</script><style>
</style>
子组件BaseSelect.vue
<template><div><select><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">广州</option><option value="105">深圳</option></select></div>
</template><script>
export default {
}
</script><style>
</style>
【代码分析】
- 父组件:定义了一个
selectId
,用于存储当前选中的城市 ID,但没有将该值传递给子组件。 - 子组件:
<select>
元素的值没有任何绑定,用户在子组件中选中城市时,父组件中的 selectId 不会自动更新。
【暴露得问题】
父组件和子组件之间的数据没有双向绑定,修改子组件中的选择不会反映到父组件的数据中。
【优化】
父组件App.vue:
<template><div class="app"><BaseSelect:cityId="selectId"@changeId="selectId=$event"></BaseSelect></div>
</template><script>
import BaseSelect from './components/BaseSelect.vue'
export default {data() {return {selectId: '102',}},components: {BaseSelect,},
}
</script><style>
</style>
子组件BaseSelect.vue:
<template><div><select :value="cityId" @change=handleChange><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">广州</option><option value="105">深圳</option></select></div>
</template><script>
export default {props:{cityId:String},methods:{handleChange(e){this.$emit('changeId',e.target.value)}}}
</script><style>
</style>
【优化思路】
手动实现双向绑定:
- 父组件:
selectId
被传递给子组件BaseSelect
,并通过@changeId
监听子组件发出的changeId
事件,将子组件的选中值($event)
更新到父组件的selectId
上。 - 子组件:子组件通过
props
接收来自父组件的cityId
,并将select
元素的value
属性与其绑定,用户选择城市时,触发@change
事件,使用this.$emit('changeId', e.target.value)
将选中的值传递回父组件。
【运行结果】
- 实现了父子组件之间的数据双向绑定。
- 当用户在子组件中选择不同的城市时,selectId 会自动更新。
- 如果 selectId 在父组件中发生变化,子组件的选择框也会同步更新。
3 v-model简化代码
1. 目标
父组件通过 v-model
简化代码,实现子组件和父组件数据 双向绑定
2. 简化思路
v-model
其实就是 :value
和 @input
事件的简写
- 子组件:
props
通过value
接收数据,事件触发input
- 父组件:
v-model
直接绑定数据
3. 示例代码
父组件App.vue
<template><div class="app"><!-- v-mdel= :value +@input--><BaseSelectv-model="selectId"></BaseSelect></div>
</template><script>
import BaseSelect from './components/BaseSelect.vue'
export default {data() {return {selectId: '102',}},components: {BaseSelect,},
}
</script><style>
</style>
子组件BaseSelect.vue
<template><div><select :value="value" @change=handleChange><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">广州</option><option value="105">深圳</option></select></div>
</template><script>
export default {props:{value:String},methods:{handleChange(e){this.$emit('input',e.target.value)}}}
</script><style>
</style>
使用 v-model
实现双向绑定:
- 父组件:通过
v-model="selectId"
将selectId
绑定到子组件的value
上。
子组件:接收一个名为value
的prop
,并使用:value="value"
来将父组件的selectId
传递给<select>
元素。当选择发生变化时,子组件会触发input
事件,父组件通过v-model
自动接收更新后的值。
【运行结果】