从文档上可以看到介绍说,v-model等价于下面这种形式。
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
去SFC跑了一下
<script setup>
import { ref } from 'vue'
const msg = ref('Hello World!')
const searchText = ref('h')
</script>
<template>
<h1>{{ msg }}</h1>
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
<input v-model="searchText" />
</template>
结果:
return (_ctx, _cache) => {
return (_openBlock(), _createElementBlock(_Fragment, null, [
_createElementVNode("h1", null, _toDisplayString(msg.value), 1 /* TEXT */),
_createElementVNode("input", {
value: searchText.value,
onInput: _cache[0] || (_cache[0] = $event => (searchText.value = $event.target.value))
}, null, 40 /* PROPS, HYDRATE_EVENTS */, _hoisted_1),
_withDirectives(_createElementVNode("input", {
"onUpdate:modelValue": _cache[1] || (_cache[1] = $event => ((searchText).value = $event))
}, null, 512 /* NEED_PATCH */), [
[_vModelText, searchText.value]
])
], 64 /* STABLE_FRAGMENT */))
}
}
可以看到其实并不相等,跑去看了源码后发现主要因为v-model其实还有别的逻辑:
created(el, { modifiers: { lazy, trim, number } }, vnode) {
el._assign = getModelAssigner(vnode)
const castToNumber =
number || (vnode.props && vnode.props.type === 'number')
addEventListener(el, lazy ? 'change' : 'input', e => {
if ((e.target as any).composing) return
let domValue: string | number = el.value
if (trim) {
domValue = domValue.trim()
}
if (castToNumber) {
domValue = looseToNumber(domValue)
}
el._assign(domValue)
})
if (trim) {
addEventListener(el, 'change', () => {
el.value = el.value.trim()
})
}
比如,后面的修饰符,以及在beforeupdate里做了点优化:
beforeUpdate(el, { value, modifiers: { lazy, trim, number } }, vnode) {
el._assign = getModelAssigner(vnode)
// avoid clearing unresolved text. #2302
if ((el as any).composing) return
if (document.activeElement === el && el.type !== 'range') {
if (lazy) {
return
}
if (trim && el.value.trim() === value) {
return
}
if (
(number || el.type === 'number') &&
looseToNumber(el.value) === value
) {
return
}
}
const newValue = value == null ? '' : value
if (el.value !== newValue) {
el.value = newValue
}
}