在学习中了解到,v-model实际上只是一个语法糖。并且Vue3对v-model的逻辑进行了重写。于是决定对Vue2和Vue3中对于v-model的实现进行探究。
v-model中触发的事件
v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
text 和 textarea 元素使用 value property 和 input 事件;
checkbox 和 radio 使用 checked property 和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。
change、blur、input事件
- change事件:只有当内容变化,并且失去焦点时才触发。没有实时性。
- input事件:在输入框输入的时候回实时响应并触发。
- blur事件:失去焦点触发。
修饰符
- .lazy 将触发的input事件改为触发change事件。
- .number 将输入值转为number类型。
- .trim 去除输入值的首位空格。
Vue2中v-model的实现(以text为例)
普通的Dom元素(原生组件)
$event是指当前触发的是什么事件(鼠标事件,键盘事件等)
$event.target则指的是事件触发的目标,即哪一个元素触发了事件,这将直接获取该dom元素
<input v-model="val">
<input :value="val" @input="val = $event.target.value">
自定义组件
如果作为子组件使用,在父组件中想实现双向绑定要怎么实现呢?
不妨先将父组件调用子组件的v-model用自己的写法重写再分析。
重写
在input中输入的值是回调函数的第一个参数(emit带回来的第一个值),所以可以用arguments对象取到。从这里我们可以有个思路,自定义组件要实现双向绑定需要满足两件事:1、子组件要接受父组件传递过来的值。2、子组件input中发生相应的修改事件后,要抛出事件,并将value值给带回来。
<component v-model="val">
<component :value="val" @input="val = arguments[0]"
子组件中的写法
在vue2中,有一个model的属性可以定义接受的属性以及外抛的事件。这个接收的属性要和传入的属性相对应起来。
这里要注意一点,如果按我下面这样写,似乎model这个属性没什么用,因为一切都是子组件和父组件的值一一对应的。但是实际情况是,正常的使用下我们并不会将父组件那一部分拆开,而是直接使用v-model了。所以model的作用就是将父子组件之间,传入的值和触发的事件一一对应起来(所以prop要和props里面获取的值一样)。
<input type="text" :value="value" @input="$emit('input',$event.target.value)">
model: {
prop: 'value',
event: 'input'
}
props: {
value: String
}
但是我们也可以发现一个问题,由于传入的值和model中的prop必须是对应的,所以一次只能绑定一个v-model。
Vue3,重写了v-model,可以绑定多个v-model
移除了model
prop默认值改为了modelValue
event默认值改为了update:modelValue
总结一下,就是可以通过v-model:xxx的方式,然后通过抛出的方法update:xxx来实现多个v-model的绑定
转载的代码,原链接
//父组件
<template>
<div>
<Child v-model:text="message" />
<div>绑定的值:{{message}}</div>
</div>
</template>
//子组件
<template>
<div>
<input
type="text"
:value="text"
@input="$emit('update:text', $event.target.value)"
>
</div>
</template>
<script>
export default {
//3.x 接收v-model冒号后面的值,相应的触发的方法改为update:text
props:['text']
}
</script>
//父组件
<template>
<div>
<Child
v-model="message1"
v-model:text="message2"
/>
<div>绑定的值1:{{message1}}</div>
<div>绑定的值2:{{message2}}</div>
</div>
</template>
//子组件
<template>
<div>
<input
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
>
<input
type="text"
:value="text"
@input="$emit('update:text', $event.target.value)"
>
</div>
</template>
<script>
export default {
//v-model冒号后面不写值,默认就是modelValue
props:['modelValue','text']
}
</script>
本文探讨了v-model在Vue2和Vue3中的工作原理,指出它是一个语法糖。在Vue2中,针对不同输入元素v-model会绑定不同的属性和事件。Vue3对v-model进行了重写,允许绑定多个v-model。文章详细阐述了change、blur、input事件的差异,并介绍了修饰符如.lazy、.number和.trim的作用。同时,分析了Vue2中自定义组件如何实现双向绑定,以及Vue3如何通过update:xxx事件支持多个v-model。
v-model的实现(Vue2和Vue3),change、blur、input事件。&spm=1001.2101.3001.5002&articleId=113867250&d=1&t=3&u=c567873b8a704cb0b487679738ce1c92)
2405

被折叠的 条评论
为什么被折叠?



