v-model实现

模拟v-model实现数据双向绑定

父组件

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
<template>
<div>
<HdInput :value="title" @update:value="change"></HdInput>
</div>
<hr>
{{ title }}
</template>

<script>
import HdInput from './components/hdInput.vue';

export default {
components: { HdInput },
data() {
return {
title: '测试'
}
},
methods: {
change(val) {
this.title = val;
}
}
}
</script>

子组件

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
<template>
<div>
<input type="text" :value="content" @input="change">
{{ content }}
</div>
</template>

<script>

export default {
props: ['value'],
emits: ['update:value'],
data() {
return {
content: this.value
}
},
methods: {
change(event) {
this.content = event.target.value;

this.$emit('update:value', this.content);
}
}
}

</script>
image-20230304171743905

这样就实现了数据双向绑定的效果。

v-model的实现方式:将父组件内向子组件传递的方法改为v-model,值改为需要监听的变量即可。

1
2
3
4
5
<template>
<div>
<HdInput :value="title" v-model:value="title"></HdInput>
</div>
</template>

v-model后面的 :value是什么意思呢?

其实就是 update方法后面传递的值。比如这里的value修改为 modelValue,那么子组件内部的接受值也需要相对应的修改。修改后与之前的效果一样。

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
<!-- 父组件 -->
<HdInput :value="title" v-model:modelValue="title"></HdInput>

<!-- 子组件 -->
<template>
<div>
<input type="text" :value="content" @input="change">
{{ content }}
</div>
</template>

<script>

export default {
props: ['modelValue'],
emits: ['update:modelValue'],
data() {
return {
content: this.modelValue
}
},
methods: {
change(event) {
this.content = event.target.value;

this.$emit('update:value', this.content);
}
}
}

</script>

v-model如果删除掉后面的参数值应该怎么处理呢?

很简单,子组件内部直接使用modelValue即可。

多个v-model的使用

利用v-model:value 的语法实现同一个组件内多个v-model属性的应用,实现对多个数据的双向绑定。

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
 <lesson v-for="item in db" :key="item.id" :lesson="item" class='hd' @del="show" v-model="item.title" v-model:price="item.price"/>

<!-- 子组件 -->
<template>
<h3 @dblclick="inpurPriceShow = true">
<input v-if="inpurPriceShow" type="text" :value="lesson.price" @input="$emit('update:price', $event.target.value)" @blur="inpurPriceShow = false" @keyup.enter="inpurPriceShow = false">
<strong v-else>{{ lesson.price }}</strong>
</h3>

<h3 @dblclick="inpurPriceShow = true">
<input v-if="inpurPriceShow" type="text" :value="lesson.price" @input="$emit('update:price', $event.target.value)" @blur="inpurPriceShow = false" @keyup.enter="inpurPriceShow = false">
<strong v-else>{{ lesson.price }}</strong>
</h3>
</template>

<script>
export default {
inheritAttrs: false,
props: ['lesson', 'modelValue', 'price'],
emits: {
'update:modelValue': null,
'price': null
},
data() {
return {
inputShow: false,
inpurPriceShow: false
}
}
}
</script>

v-model自定义修饰符

v-model内置的修饰符:

名称 作用 说明
trim 移除用户输入的内容两端的空格 不会移除中间的空格
lazy 使表单监听 change 事件而不是 input 也就是表单数据在发生变化时才会通知去改变响应式数据
number 将输入的合法符串转为数字 遇到处理不了的会返回输入值

自定义修饰符官方文档参考

组件的 v-model 上所添加的修饰符,可以通过 modelModifiers prop 在组件内访问到。当然,如果v-model后加上了:value等参数,那么获取自定义修饰符的时候也需要进行相对应的修改,modelModifiers修改为valueModifiers.

v-model修饰符可以连续使用

使用方法:直接在v-mode后面使用 . 调用即可。

__END__