欢迎大家讨论学习
文章目录
前言
这里主要介绍v-model在表单元素上的使用和原理,摸清原理后,对v-model在组件中的使用有很大帮助,后续会慢慢介绍在组件中的应用
v-model是Vue框架的一个指令,v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
提示:以下是本篇文章正文内容,下面案例可供参考
一、须知
- v-model 会忽略所有表单元素的 value、checked、selected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。
- v-model 在内部为不同的输入元素使用不同的property 并抛出不同的事件:
- text 和 textarea 元素使用 value property 和 input 事件;
- radio 和checkbox 使用 checked property 和 change 事件;
- select 字段将 value 作为 prop 并将 change 作为事件。
- v-model双向数据绑定的关键(重中之重):
- 数据---->视图
通过v-bind: 将属性和响应式数据进行绑定,实现数据改变---->视图改变 - 视图---->数据
用户与视图进行交互,会触发相应的事件(v-on:),然后通过事件处理函数将新数据重新更新到属性依赖的响应式数据(其实就是数据的更新),实现视图改变---->数据改变
二、使用及原理
1. text和textarea
text文本
关键代码如下(示例):
<!-- text的使用-->
账户: <input type="text" v-model = "account"> <br><br>
<!-- text的原理 -->
密码: <input type="password" :value="password" @input="password = $event.target.value">
textarea文本域
textarea文本域和text文本的使用和原理一模一样
2. radio 和checkbox
radio单选框
关键代码如下(示例):
<!-- radio的使用-->
<!-- 这里需要我们自己手动添加value,因为我们需要拿到新数据重新更新到属性所绑定的数据 -->
男: <input type="radio" name="gender" value="male" v-model="gender">
<!-- radio的原理 -->
女: <input type="radio" name="gender" value="female" :checked="gender === 'female'" @change="gender = $event.target.value">
checkbox复选框
(1)单个复选框(绑定到布尔值,不用手动加value)
关键代码如下(示例):
<!-- checkbox的使用-->
<input type="checkbox" v-model="agree">阅读并接受《用户协议》
<!-- checkbox的原理 -->
<input type="checkbox" :checked="agree" @change="agree = $event.target.checked">阅读并接受《用户协议》
(2)多个复选框(绑定到同一个数组,用手动加value)
关键代码如下(示例):
爱好:
<!-- checkbox的使用-->
吃饭: <input type="checkbox" name="hobby" value="eat" v-model="hobby">
睡觉: <input type="checkbox" name="hobby" value="sleep" v-model="hobby">
<!-- checkbox的原理 -->
打豆豆: <input type="checkbox" name="hobby" value="play" :checked= "hobby.indexOf('play') !== -1" @change="changeHobby">
-------------------------------------------------------
// hobby需要用一个数组来接收 hobby: [],
changeHobby(){
if (this.hobby.indexOf('play') === -1) {
// 没有该项时,change事件后就添加
this.hobby.push('play')
} else {
// 有该项时,change事件后就删除
const index = this.hobby.indexOf('play')
this.hobby.splice(index, 1)
}
}
3. select
select选择框
关键代码如下(示例):
<!-- select的使用-->
居住地:
<select v-model="city1">
<option>北京</option>
<option>上海</option>
<option>广州</option>
<option>深圳</option>
</select> <br><br>
<!-- select的原理 -->
籍贯:
<select :value="city2" @change="city2 = $event.target.value">
<option>北京</option>
<option>上海</option>
<option>广州</option>
<option>深圳</option>
</select> <br><br>
期间用到的data:
data: {
account: '',
password: '',
gender: '',
hobby: [],
city1: '北京',
city2: '上海',
agree: '',
}
补充
一定一定要好好研读上面“须知”的第三条!!!
看完上述内容,你们可能还会有这样的疑惑: 为什么radio和checkbox在使用的过程中需要手动添加value属性???
我们可以这样理解(超详细):
- 根据须知2我们知道,在v-model内部radio和checkbox是使用 checked property 和 change 事件实现的。
- 根据须知3我们知道,触发事件后,通过事件处理函数,我们需要拿到新数据,然后重新更新到属性所依赖的响应式数据。
- 在text/textarea/select中,我们可以通过value拿到新数据来重新更新数据。但是,在radio和checkbox中,我们没办法拿到选中的新数据,这时我们就需要手动设置value值,使得在事件处理函数中可以使用该值。
而为什么单个复选框不需要手动设置value值???
这是因为单个复选框绑定的是布尔值,在其事件处理函数中可以拿到新数据,可以做到数据的更新。
我们还可以直接这样理解(简略版):
直接看事件处理函数,它想要更新数据,就看它以现有的条件能不能拿到新数据,如果不能就需要手动设置value值,从而拿到新数据,然后进行数据的更新。
总结
v-model在表单元素的使用时,我们只需记住:
radio和checkbox(多个复选框)需要手动添加value值。
后续还会更新v-model双向数据绑定在组件中的应用,感谢大家的关注
来了来了,接下来继续给大家介绍一下v-model在组件中的应用
三、v-model在组件中的应用
为了方便表单元素复用,我们通常把表单元素封装成表单类组件
下面介绍v-model在组件中的应用
核心:一个组件上的 v-model 默认会利用名为 value的 属性 和名为 input 的事件
提示:在此之前你应该掌握组件通讯相关知识
实现双向数据绑定的核心:
①父传子:数据应该是父组件props传递过来的,子组件内将v-model拆解绑定数据
②子传父:通过自定义事件,子组件将新值传递给父组件修改
1. 表单类组件封装
先给大家介绍一下不使用v-model时的用法
关键代码如下(示例):
父组件:
<!-- 注意:组件上绑定的事件默认都是自定义事件 -->
<City :cityId="selectId" @changeId="selectId = $event"></City>
子组件:
<!-- 注意:这里不能直接使用v-model实现双向数据绑定,
因为这里的数据是父组件传递过来的,不能直接修改,所以要将v-model拆解绑定数据 -->
<select :value="cityId" @change="change">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">深圳</option>
</select>
...
// 接收父组件传过来的数据
props:['cityId'],
methods: {
change(e){
// 触发自定义事件
this.$emit('changeId', e.target.value)
}
}
2. 使用v-model简化代码
上面的代码可以简化写成这样
父组件:
<City v-model="selectId"></City>
<!-- 上面这段代码等价于下面这段代码 -->
<!-- <City :value="selectId" @input="selectId = $event"></City> -->
子组件:
<select :value="value" @change="change">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广州</option>
<option value="4">深圳</option>
</select>
...
// 当在组件上使用v-model时,这里的变量名必须是 value
props:['value'],
methods: {
change(e){
// 当在组件上使用v-model时,这里自定义事件的名字必须是 input
this.$emit('input', e.target.value)
}
}
拓展
有的小伙伴可能会有这样的想法(错误的):这是不是就是为了凑成v-model拆分出来的属性和事件,那这个自定义事件名可不可以改成change,因为value属性和change事件也可以凑成v-model
答案是不能
因为一个组件上的 v-model 默认会利用名为 value 的 属性 和名为 input 的事件(核心)
然而我们知道单选框、复选框等类型的输入控件对于value有不同的目的。
我们可以通过model 选项来修改这种默认情况
以radio单选框为例
父组件:
<Gender v-model="gender"></Gender>
<!-- 上面这段代码等价于下面这段代码 -->
<!-- <Gender :gender="gender" @change="gender= $event"></Gender> -->
子组件:
男:<input type="radio" name="性别" value="male" :checked="gender === 'male'" @change="$emit('change',$event.target.value)">
女:<input type="radio" name="性别" value="female" :checked="gender === 'female'" @change="$emit('change', $event.target.value)">
...
// 修改v-model的默认
// 一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件
model: {
prop: 'gender',
event: 'change'
},
props: ['gender']
v-model在表单元素的使用和在组件中的使用原理不同:
① 在表单元素上,v-model 在内部为不同的输入元素使用不同的property 并抛出不同的事件
② 在组件上,v-model 默认会利用名为 value的属性和名为input的事件
3. .sync 修饰符
作用:可以实现子组件与父组件数据的双向绑定
特点:prop属性名,可以自定义,非固定为value
本质:就是 :属性名 和 @update:属性名 的合写
父组件:
<Home :homeId.sync="id"></Home>
<!-- 上面这段代码等价于下面这段代码 -->
<!-- <Home :homeId="id" @update:homeId="id = $event"></Home> -->
子组件:
<select :value="homeId" @change="change">
<option value="1">山东</option>
<option value="2">山西</option>
<option value="3">河南</option>
<option value="4">河北</option>
</select>
...
props:['homeId'],
methods: {
change(e){
this.$emit('update:homeId', e.target.value)
}
},
和v-model相比,.sync修饰符的优点:更加灵活简便
本质都一样:①父传子:数据是父组件props传递过来的 ②子传父:通过自定义事件,子组件将新值传递给父组件修改