v-model详解

871 词

v-model 详解#

v-model 原理#

原理:v-model本质上是一个语法糖。例如应用在输入框上,就是value属性和input事件的合写,而复选框就是checked属性和change事件的合写
作用:提供数据的双向绑定

  1. 数据变,视图跟着变:value
  2. 视图变,数据跟着变@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 的语法糖:

  1. 箭头函数:箭头函数是一种更简洁的函数定义方式,可以用来替代传统的函数定义方式。
  2. 模板字符串:模板字符串是一种更灵活的字符串拼接方式,可以使用变量、表达式等。
  3. 解构赋值:解构赋值是一种更方便的变量赋值方式,可以将数组或对象的属性解构为单独的变量。
  4. 简写对象字面量:简写对象字面量是一种更简洁的对象定义方式,可以省略属性名和冒号。

表单类组件封装 & v-model 简化代码#

表单类组件封装#

  1. 父传子:数据应该是父组件props传递过来,v-model不能直接修改数据,所以需要拆解绑定数据
  2. 子传父:监听输入,子传父传值给父组件修改

实例#

地区下拉框组件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简化代码,实现子组件和父组件数据双向绑定

  1. 子组件中:props通过value接收,事件触发input
  2. 父组件中: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>