表单v-model
- parse的时候添加属性, generate的时候处理属性
- processAttrs调用addDirective往el.directives添加指令信息
parse 阶段
v-model
被当做普通的指令解析到 el.directives 中,12345678910111213141516171819202122232425262728function processAttrs (el) {var list = el.attrsList;var i, l, name, rawName, value, modifiers, syncGen, isDynamic;for (i = 0, l = list.length; i < l; i++) {name = rawName = list[i].name;value = list[i].value;if (dirRE.test(name)) {name = name.replace(dirRE, '');addDirective(el, name, rawName, value, arg, isDynamic, modifiers, list[i]);} else {// 文本}}}function addDirective (// dom, name, 属性值el, name, rawName, value, arg, isDynamicArg, modifiers, range) {(el.directives || (el.directives = [])).push(rangeSetItem({name: name,rawName: rawName,value: value,arg: arg,isDynamicArg: isDynamicArg,modifiers: modifiers}, range));el.plain = false;}
generate 阶段
- generate->genElement->genData$2->genDirectives , 添加回调对应的函数字符串
const dirs = genDirectives(el, state)
- state
var state = new CodegenState(options);
, options在createCompiler
中合并baseOption得来 主要是通过添加以下两个属性实现v-model语法糖
12addProp(el, 'value', ("(" + value + ")")); // el上添加propsaddHandler(el, event, code, null, true); //v-model处理了composition, 输入法完成输入前不修改model的值
123456789101112131415161718{"directives": [{"name": "model","rawName": "v-model","value": message,"expression": "message"}],"attrs": { "placeholder": "edit me" },"domProps": { "value": message },"on": {"input": function($event) {if ($event.target.composing) return;message = $event.target.value;}}}
|
|
|
|
|
|
|
|
运行时指令机制对composition处理
- createRenderFunction时会加指令模板的hook, 这些hook会在patch的时候执行
- 指令module的update hook会查找指令的定义function, 然后通过
callHook$1
执行对应的钩子(create只是添加 insert到vnode的hook里, insert执行要等到patch结束之前)
|
|
|
|
组件v-model
- parse 阶段和表单v-model一样
generate 阶段
- runtime不再需要, 添加了model而不是directive字符串
|
|
运行时生成语法糖
- 没有涉及model指令, 就是往组件上增加props,on属性1234567891011121314151617181920212223242526272829function createComponent () {// transform component v-model data into props & eventsif (isDef(data.model)) {transformModel(Ctor.options, data);}}// transform component v-model info (value and callback) into// prop and event handler respectively.function transformModel (options, data) {var prop = (options.model && options.model.prop) || 'value'; // 可在子组件中定义事件名和props属性名var event = (options.model && options.model.event) || 'input';(data.attrs || (data.attrs = {}))[prop] = data.model.value;var on = data.on || (data.on = {});var existing = on[event];var callback = data.model.callback;if (isDef(existing)) {if (Array.isArray(existing)? existing.indexOf(callback) === -1: existing !== callback) {on[event] = [callback].concat(existing);}} else {on[event] = callback;}}