// 52 行
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[assignKey](domValue)
})
// 68 行
if (!lazy) {
addEventListener(el, 'compositionstart', onCompositionStart)
addEventListener(el, 'compositionend', onCompositionEnd)
// Safari < 10.2 & UIWebView doesn't fire compositionend when
// switching focus before confirming composition choice
// this also fixes the issue where some browsers e.g. iOS Chrome
// fires "change" instead of "input" on autocomplete.
addEventListener(el, 'change', onCompositionEnd)
}
trim
去除输入的首尾。change 事件和 input 事件都侦听。
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[assignKey](domValue)
})
if (trim) {
addEventListener(el, 'change', () => {
el.value = el.value.trim()
})
}
number
会将 DOM 的值转为 number 类型后再赋值给数据。
const castToNumber =
number || (vnode.props && vnode.props.type === 'number')
// ...
if (castToNumber) {
domValue = looseToNumber(domValue)
}
// shared/src/general.ts
export const looseToNumber = (val: any): any => {
const n = parseFloat(val)
return isNaN(n) ? val : n
}
mounted 钩子
// 79 行
mounted(el, { value }) {
el.value = value == null ? '' : value
},
v-model 指令就是一种双向绑定的实现。v-model 指令常用于表单元素上,当表单元素输入发生改变之后,会通知数据模型更新。反之,数据模型发生改变之后,也会同步的显示到界面上。
v-model 里面的实现:created、mounted 和 beforeUpdate 三个钩子函数
源码实现目录:
runtime-dom/src/directives/vModel.ts
修饰符
v-model 的修饰符有 modifiers:lazy、trim、number
lazy
lazy 修饰符,侦听的是 input 的 change 事件,它不会再 input 输入框实施输入的时候触发,而会在 input 元素值改变且失去焦点的时候触发。如果不设置 lazy,侦听的就是 input 的 input 事件,它会在用户实时输入的时候触发。此外,还会多侦听 compositionstart 和 compositioned 事件(非 lazy 态)。
compositionstart 设置
e.target.composing = true
compositionend 设置e.target.composing = false
同时触发 input 事件trim
去除输入的首尾。change 事件和 input 事件都侦听。
number
会将 DOM 的值转为 number 类型后再赋值给数据。
mounted 钩子
总结
v-model 指令才是阵子意义上的双向绑定,因为数据的流动是双向的,它可以作用于原生的表单元素,也可以作用于自定义指令。
当 v-model 作用于表单元素时,它会借助指令的钩子函数在元素挂载之后把数据赋值给表单元素,在数据变化完成之后,在更新之前,把数据再次赋值给表单元素,这就是数据变化引起 DOM 变化的过程。
此外,表单元素会侦听相关事件,比如 input 标签会侦听 change 或者 input 事件,在事件回调函数中修改数据的值,这就是 DOM 变化引起数据变化的过程。