最近小组有个关于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.www.ysyl157.com   name为model,对应的state.directives[dir.name]相当于state.www.gouyiflb.cn  directives[model],directives的定义位于src/platforms www.dasheng178.com /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的结构如下:

这个方法其实是在input上动态绑定了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上。
即,以下两份代码其实是一个意思。
第一份:

第二份

[Vue源码分析] v-model实现原理的更多相关文章

  1. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  2. 前端Vue 源码分析-逻辑层

    Vue 源码分析-逻辑层 预期的效果: 监听input的输入,input在输入的时候,会触发 watch与computed函数,并且会更新原始的input的数值.所以直接跟input相关的处理就有3处 ...

  3. jQuery 2.0.3 源码分析Sizzle引擎解析原理

    jQuery 2.0.3 源码分析Sizzle引擎 - 解析原理 声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 先来回答博友的提问: 如何解析 div > p + ...

  4. Vue源码分析(一) : new Vue() 做了什么

    Vue源码分析(一) : new Vue() 做了什么 author: @TiffanysBear 在了解new Vue做了什么之前,我们先对Vue源码做一些基础的了解,如果你已经对基础的源码目录设计 ...

  5. vue 快速入门 系列 —— 侦测数据的变化 - [vue 源码分析]

    其他章节请看: vue 快速入门 系列 侦测数据的变化 - [vue 源码分析] 本文将 vue 中与数据侦测相关的源码摘了出来,配合上文(侦测数据的变化 - [基本实现]) 一起来分析一下 vue ...

  6. 【MyBatis源码分析】插件实现原理

    MyBatis插件原理----从<plugins>解析开始 本文分析一下MyBatis的插件实现原理,在此之前,如果对MyBatis插件不是很熟悉的朋友,可参看此文MyBatis7:MyB ...

  7. SOFA 源码分析 — 自定义线程池原理

    前言 在 SOFA-RPC 的官方介绍里,介绍了自定义线程池,可以为指定服务设置一个独立的业务线程池,和 SOFARPC 自身的业务线程池是隔离的.多个服务可以共用一个独立的线程池. API使用方式如 ...

  8. Spring Boot源码分析-配置文件加载原理

    在Spring Boot源码分析-启动过程中我们进行了启动源码的分析,大致了解了整个Spring Boot的启动过程,具体细节这里不再赘述,感兴趣的同学可以自行阅读.今天让我们继续阅读源码,了解配置文 ...

  9. 内核通信之Netlink源码分析-用户内核通信原理

    2017-07-05 本节从一个小案例入手,结合源码分析下通过netlink进行内核和用户通信的流程. 内核端 按照传统CS模式,其实内核端可以作为是服务器端,用以接收用户的请求并作出处理,但是从ne ...

随机推荐

  1. 利尔达NB-IOT模组Coap数据AT+NMGS发送时返回-513的原因

    1. 利尔达NB-IOT模组使用AT+NMGS发送数据,返回-513的问题,大致有3种可能性,在硬件上,模组的射频电路分为A型和B型模组,所以烧写固件的时候,也要分为A和B型固件,如果烧写反了,那么R ...

  2. Ruby 基础教程 1-2

    1.数组 创建 arrayname=[] arrayname=["1",12,"23"] 访问 arrayname[index] 更新 arrayname[in ...

  3. Java进阶知识点:并发容器背后的设计理念

    一.背景 容器是Java编程中使用频率很高的组件,但Java默认提供的基本容器(ArrayList,HashMap等)均不是线程安全的.当容器和多线程并发编程相遇时,程序员又该何去何从呢? 通常有两种 ...

  4. ubuntu ssh配置

    Secure Shell (SSH) is a cryptographic network protocol for operating network services securely over ...

  5. POJ 2987 Firing(最大流最小割の最大权闭合图)

    Description You’ve finally got mad at “the world’s most stupid” employees of yours and decided to do ...

  6. 微信小程序如何获取openid

    微信小程序如何获取openid wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId // ...

  7. Hadoop之block研究

        本文翻译原链接:https://hadoopabcd.wordpress.com/2015/03/17/hdfs-file-blocks-distribution-in-datanodes/ ...

  8. spring 国际化i18n配置

    i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是“国际化”的简称.在资讯领域,国际化(i18n)指让产品(出版物,软件,硬件等)无需做大的改 ...

  9. Java容器之Collections

    Collections 类来源于 java.util.Collections,从 java.lang.object继承. 此类完全由在 collection 上进行操作或返回 collection 的 ...

  10. 求gcd(最大公因数),lcm(最小公倍数)模板

    gcd(最大公因数),lcm(最小公倍数) #include<iostream> using namespace std; int gcd(int a,int b)//辗转相除法(欧几里德 ...