[Vue源码分析] v-model实现原理
[Vue源码分析] v-model实现原理最近小组有个关于vue源码分析的分享会,提前准备一下…前言:我们都知道使用v-model可以实现数据的双向绑定,及实现数据的变化驱动dom的更新,dom的更新影响数据的变化。那么v-model是怎么实现这一原理的呢?接下来探索一下这部分的源码。
最近小组有个关于vue源码分析的分享会,提前准备一下…
前言:
我们都知道使用v-model可以实现数据的双向绑定,及实现数据的变化驱动dom的更新,dom的更新影响数据的变化。那么v-model是怎么实现这一原理的呢?接下来探索一下这部分的源码。
前期准备
①:vue2.5.2源码(用于阅读、查看关联等)
②:建立vue demo,创建包含v-model指令的实例(用于debugger)
以下为demo:
genDirectives
在模板的编译阶段, v-model跟其他指令一样,会被解析到 el.directives 中,之后会通过genDirectives方法处理这些指令,genDirectives方法位于src/compiler/codegen/index.js中:
我们去到之前建立的demo,找到demo中node_modules/vue/dist/vue.esm.js下的genDirectives方法,打上debugger,如图:
可以看到传进来的el是ast语法树,el.directives是el上的指令,如下:
回到genDirectives
源码,循环指令时都执行了const gen: DirectiveFunction = state.directives[dir.name]
这个方法,state.directives
是什么?
当遍历到v-model
的时候,dir.name
为model
,对应的state.directives[dir.name]
相当于state.directives[model]
,directives
的定义位于src/platforms/web/compiler/directives/index.js
中:
本次分析的v-model
,对应的也就是model
方法,也就是其实!!gen(el, dir, state.warn)
执行的是model
方法,!!
用于将返回值转为Boolean
类型,model
的定义位于index
同目录下。
model
model
方法根据传入的参数对tag
的类型进行判断,调用不同的处理逻辑,本demo中tag
的类型为input
,所以会执行genDefaultModel
方法,为了节约时间,就不去源码中找了,藏得比较深,直接在demo引用的单文件源码vue.esm.js
中搜索genDefaultModel
。
genDefaultModel
发现定义如下,打上debugger,以便调试:
通过控制台查看变量信息,可以看到:
可以看到里边的genAssignmentCode(value, valueExpression)
在此demo中相当于genAssignmentCode("msg", ""$event.target.value"")
,执行此方法后返回的是一个字符串:msg=$event.target.value
,后来命中了needCompositionGuard
,所以code
变成了if($event.target.composing)return;msg=$event.target.value
,if($event.target.composing)return;
的作用是不记录用户未确定的输入,比如:
注释掉if(needCompositionGuard)
的话用户没确定的也会展示,如图:
随后会依次执行以下两个方法:
addProp
先注释掉addHandler
,避免对研究此方法产生影响。
可以看到此方法的功能为给el
添加props
,首先判断el
上有没有props
,如果没有的话创建props
并赋值为一个空数组,随后拼接对象并推到props
中,代码在此demo中相当于push
了{name: "value", value: "(msg)"}
,打印一下这番操作后的el,可以看到添加了props
的el
的结构如下:
这个方法其实是在inpu
t上动态绑定了value
,此时,原本的<input v-model="msg">
相当于变成了<input v-bind:value="msg">
,随后继续执行addHandler
。
addHandler
以下仅包含关键代码,打上debugger
以便查看数据。
控制台查看el
的debuuger
结果:
可以看到比执行addHandler
之前,el
上多了events
,可以得知这个方法主要给el
添加了事件处理,在此demo中的话相当于在 input 上绑定了 input 事件。
总结:
也就是说,到此为止,原本的<input v-model="msg">
相当于变成了<input v-bind:value="msg" v-on:input="msg=$event.target.value">
,当用户输入的使用触发msg=$event.target.value
进而更新msg
,msg
通过v-bind
绑定到输入框的value上。
即,以下两份代码其实是一个意思。
第一份:
第二份
更多推荐
所有评论(0)