v-model简介
v-model是Vue用于表单元素上创建双向数据绑定,它本质是一个语法糖,在单向数据绑定的基础上,增加了监听用户输入事件并更新数据的功能。
实例代码
<div id="test">
请输入:<input type="text" v-model="message"><br/>
你输入的是:<input type="text" v-model="message" disabled >
</div>
genDirectives
vue通过 genDirectives来初始化指令。
function genDirectives (el, state) {
var dirs = el.directives;
if (!dirs) { return }
var res = 'directives:[';
var hasRuntime = false;
var i, l, dir, needRuntime;
for (i = 0, l = dirs.length; i < l; i++) {
dir = dirs[i];
needRuntime = true;
var gen = state.directives[dir.name];
if (gen) {
// compile-time directive that manipulates AST.
// returns true if it also needs a runtime counterpart.
needRuntime = !!gen(el, dir, state.warn);
}
if (needRuntime) {
hasRuntime = true;
res += "{name:\"" + (dir.name) + "\",rawName:\"" + (dir.rawName) + "\"" + (dir.value ? (",value:(" + (dir.value) + "),expression:" + (JSON.stringify(dir.value))) : '') + (dir.arg ? (",arg:" + (dir.isDynamicArg ? dir.arg : ("\"" + (dir.arg) + "\""))) : '') + (dir.modifiers ? (",modifiers:" + (JSON.stringify(dir.modifiers))) : '') + "},";
}
}
if (hasRuntime) {
return res.slice(0, -1) + ']'
}
}
在genDirectives函数生成对应的为之后操作所需要得一些json数据。
genDefaultModel
在给页面上绑定了v-model之后,就会根据表单元素的tag标签以及type属性的值,去调用不同的model方法,这里我们调用genDefaultModel
function genDefaultModel (
el,
value,
modifiers
) {
var type = el.attrsMap.type;
// warn if v-bind:value conflicts with v-model
// except for inputs with v-bind:type
if (process.env.NODE_ENV !== 'production') {
var value$1 = el.attrsMap['v-bind:value'] || el.attrsMap[':value'];
var typeBinding = el.attrsMap['v-bind:type'] || el.attrsMap[':type'];
if (value$1 && !typeBinding) {
var binding = el.attrsMap['v-bind:value'] ? 'v-bind:value' : ':value';
warn$1(
binding + "=\"" + value$1 + "\" conflicts with v-model on the same element " +
'because the latter already expands to a value binding internally',
el.rawAttrsMap[binding]
);
}
}
var ref = modifiers || {};
var lazy = ref.lazy;
var number = ref.number;
var trim = ref.trim;
var needCompositionGuard = !lazy && type !== 'range';
var event = lazy
? 'change'
: type === 'range'
? RANGE_TOKEN
: 'input';
var valueExpression = '$event.target.value';
if (trim) {
valueExpression = "$event.target.value.trim()";
}
if (number) {
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()');
}
}
genDefaultModel先是去检测该表单元素是否同时有v-model绑定和v-bind:value。获取到表单元素的修饰符lazy(替换input的change时间),number(入字符串转为数字)及trim.(去除两边空格),之后生成值得表达式,通过genAssignmentCode()方法生成v-model value值得代码。根据本文的例子返回的结果就是"message=$event.target.value"。最后添加响应的事件和属性。
总结
<div id="test">
请输入:<input type="text" v-model="message"><br/>
你输入的是:<input type="text" v-model="message" disabled >
</div>
这一句代码经过vue的处理之后,就变成了<input type="text" v-bind:value="message" v-on:input="message= $event.target.value"><br/>
相当于将data里面的值通过响应式更新到视图上,然后给input绑定change事件,在改变值得时候对data里面message值做修改并更新视图。