function updateDOMProps (oldVnode, vnode) {
if (isUndef(oldVnode.data.domProps) && isUndef(vnode.data.domProps)) {
return
}
var key, cur;
var elm = vnode.elm;
var oldProps = oldVnode.data.domProps || {};
var props = vnode.data.domProps || {};
// clone observed objects, as the user probably wants to mutate it
if (isDef(props.__ob__)) {
props = vnode.data.domProps = extend({}, props);
}
for (key in oldProps) {
if (isUndef(props[key])) {
elm[key] = '';
}
}
for (key in props) {
cur = props[key];
...
// 如果是input的value属性
if (key === 'value') {
// store value as _value as well since
// non-string values will be stringified
elm._value = cur;
// avoid resetting cursor position when value is the same
var strCur = isUndef(cur) ? '' : String(cur);
if (shouldUpdateValue(elm, strCur)) {
// 更新dom对应的value值
elm.value = strCur;
}
} else {
elm[key] = cur;
}
}
}
v-model的实现
v-model
是Vue
内部实现的一个指令。它所提供的基本功能是在一些表单元素上实现数据的双向绑定。基本的使用方法就是:页面初次渲染完成后,
input
输入框的值为default val
,当你改变input
输入框的值的时候,你会发现控制台也打印出了输入框当中新的值。接下来我们就来看下v-model
是如何完成数据的双向绑定的。首先第一步,在这个
vue
实例化开始后,首先将data
属性数据变成响应式的数据。接下来完成页面的渲染工作的时候,首先编译html
模板:接下来我们深入细节的看下整个绑定的过程,以及在页面当中修改
input
输入框中的值后,如何使得模型数据也发生变化。示例当中是在
input
元素上绑定的v-model
指令,它是属于built in elements
,因此不同于自定义component
创建VNode
过程中还需要进行获取props
属性,自定义事件,初始化钩子函数等,而attrs
,domProps
,on
属性最终都会绑定到dom
元素上。当调用
_c
方法完成后,即VNode
都已经生成完毕,开始将VNode
渲染成真实的dom
节点并挂载到document
中去:在页面初始化的阶段:
// TODO: 递归如何描述
在渲染
VNode
过程当中,如果是自定义的component VNode
,那么首先完成component
的vm
实例化,接下来递归的对子节点进行实例化注意当子 VNode 全部渲染成真实的 dom 节点,并挂载到父节点后,开始调用
invokeCreateHooks
方法,触发dom
节点create
阶段所包含的钩子函数来完成对dom
节点添加attrs
,domProps
,dom事件
等:(具体的可参见 createPatchFunction 方法中对于 create 阶段所有的回调函数的初始化)在这里我们只关心和
v-model
相关的domProps
和dom事件
的钩子函数,首先来看下更新domProps
的钩子函数:在
dom
初次创建的过程中,通过updateDOMProps
方法完成dom
的value
的初始化。接下来看下是如何绑定
dom
事件的:在本例当中,即向
input
节点绑定input
事件:当改变
input
输入框的内容时,触发input
事件执行对应的回调函数,这个时候便会改变响应式数据val
的值,即调用val
的setter
方法。因为之前在创建 input 的 VNode 的时候,val 收集到了这个 VNode 对应的 render watcher。所以当 val 的 setter 被触发的时候,会让 input 对应的 render watcher 重新执行,这样也就会触发这个 dom 节点的 diff 和渲染的工作。// 创建
VNode
环节 // 渲染的环节 // 绑定dom// TODO: 总体的的概述 // 如何绑定/更新domProps // 绑定原生的dom事件 // 和dom相关的attrs、domProps、原生的dom事件、style等,都是在将vnode渲染成真实的dom元素后,并关在到父dom节点后完成的。