v-model 详解
v-model 原理
原理:v-model
本质上是一个语法糖。例如应用在输入框上,就是value
属性和input
事件的合写,而复选框就是checked
属性和change
事件的合写
作用:提供数据的双向绑定
- 数据变,视图跟着变
:value
- 视图变,数据跟着变
@input
注意:$event
用于在模板中,获取事件的形参
1 2 3 4 5 6 7
| <template> <div id="app"> <input v-model="msg" type="text" /> <input :value="msg" @input="msg = $event.target.value" type="text" /> </div> </template>
|
语法糖
语法糖是指一些在编程语言中增加的语法,它们不会改变语言的功能,但可以使代码更易读、更易写、更易理解。这些语法通常是一些简洁的表达方式,可以让开发者更快地编写代码,减少代码量和重复性。
以下是一些 JavaScript 的语法糖:
- 箭头函数:箭头函数是一种更简洁的函数定义方式,可以用来替代传统的函数定义方式。
- 模板字符串:模板字符串是一种更灵活的字符串拼接方式,可以使用变量、表达式等。
- 解构赋值:解构赋值是一种更方便的变量赋值方式,可以将数组或对象的属性解构为单独的变量。
- 简写对象字面量:简写对象字面量是一种更简洁的对象定义方式,可以省略属性名和冒号。
表单类组件封装 & v-model 简化代码
表单类组件封装
- 父传子:数据应该是父组件
props
传递过来,v-model
不能直接修改数据,所以需要拆解绑定数据
- 子传父:监听输入,子传父传值给父组件修改
实例
地区下拉框组件BaseSelect.vue
封装
由父组件提供地区数据及被选中的城市 id,用v-on
将数据绑定到子组件标签上
子组件以props
接收数据,同时进行类型校验,之后正常使用
原本用v-model
即可完成数据的双向绑定,但在本例中,子组件数据由外部提供,所以拆分为v-bind:value
绑定选择地区,v-on:change
监听选择变化
1 2 3
| <select :value="cityId" @change="handleChange"> <option v-for="item in areas" :key="item.id" :value="item.id">{{ item.name }}</option> </select>
|
在选择的地区发生变化后,v-on:change
所绑定的监听事件就能够向父组件发通知,传递并更新数据
源码:
App.vue
:
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 32 33 34
| <template> <div class="app"> <BaseSelect :cityId="selectId" :areas="areaList" @changeId="selectId = $event"></BaseSelect> </div> </template>
<script> import BaseSelect from './components/BaseSelect.vue'; export default { data() { return { selectId: '104', areaList: [ { id: 101, name: '北京' }, { id: 102, name: '上海' }, { id: 103, name: '武汉' }, { id: 104, name: '广州' }, { id: 105, name: '深圳' }, ], }; }, components: { BaseSelect, }, methods: { handleChange(e) { console.log(e); this.selectId = e; }, }, }; </script>
<style></style>
|
BaseSelect.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <template> <div> <select v-bind:value="cityId" v-on:change="handleChange"> <option v-for="item in areas" :key="item.id" :value="item.id">{{ item.name }}</option> </select> </div> </template>
<script> export default { props: { cityId: String, areas: Array, }, methods: { handleChange(e) { this.$emit('changeId', e.target.value); }, }, }; </script>
<style></style>
|
v-model 简化代码
父组件v-model
简化代码,实现子组件和父组件数据双向绑定
- 子组件中:
props
通过value
接收,事件触发input
- 父组件中:
v-model
给组件直接绑数据(:value+@input)
BaseSelect.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <template> <div> <select v-bind:value="value" v-on:change="handleChange"> <option v-for="item in areas" :key="item.id" :value="item.id">{{ item.name }}</option> </select> </div> </template>
<script> export default { props: { value: String, areas: Array, }, methods: { handleChange(e) { this.$emit('input', e.target.value); }, }, }; </script>
<style></style>
|
App.vue
:
1 2 3 4 5
| <template> <div class="app"> <BaseSelect :areas="areaList" v-model="selectId"></BaseSelect> </div> </template>
|