Vue 为v-model 指令提供了lazy number trim 三种修饰符,分别对v-model的值的行为和内容进行控制。
用法:
<input v-model.lazy="val1"/>
<input v-model.number="val1"/>
<input v-model.trim="val1"/>
1.lazy
使用.lazy 可以让val1的变化由input事件转化为change事件的时机触发,也就是说用户在输入的时候不会触发,只有在blur的时候才会触发。
源码:
// 判断是否lazy,如果是lazy 将event 改为change,否则是input
var event = lazy
? 'change'
: type === 'range'
? RANGE_TOKEN
: 'input';
2.trim
使用.trim 默认会对事件的event.target.value 调用一次trim方法
源码:
if (trim) {
valueExpression = "$event.target.value.trim()";
}
3.number
使用.number 默认会对值进行一个parseFloat的转换,如果转换失败,保留原来的值。
源码:
//_n对应的是 toNumber 方法
if (number) {
valueExpression = "_n(" + valueExpression + ")";
}
// 省略N行代码
function toNumber (val) {
var n = parseFloat(val);
return isNaN(n) ? val : n
}
这里需要注意的是,如果转化失败,将返回原来的值,这里是大家容易搞错的地方,并不是设置了.number 就无法输入其他非数字字符。
完整的源代码如下:
function genDefaultModel (
el,
value,
modifiers
) {
// 省略N行代码
var ref = modifiers || {};
var lazy = ref.lazy;
var number = ref.number;
var trim = ref.trim;
var needCompositionGuard = !lazy && type !== 'range';
// 判断是否lazy,如果是lazy 将event 改为change,否则是input
var event = lazy
? 'change'
: type === 'range'
? RANGE_TOKEN
: 'input';
var valueExpression = '$event.target.value';
if (trim) { // trim的情况下,会将表达式里加入调用trim的逻辑
valueExpression = "$event.target.value.trim()";
}
if (number) {// 如果是number,调用_n 来包裹表达式内容,_n对应的是 toNumber 方法
valueExpression = "_n(" + valueExpression + ")";
}
var code = genAssignmentCode(value, valueExpression);
if (needCompositionGuard) {
code = "if($event.target.composing)return;" + code;
}
addProp(el, 'value', ("(" + value + ")"));
addHandler(el, event, code, null, true);
if (trim || number) {
addHandler(el, 'blur', '$forceUpdate()');
}
}