[Vue源码分析] v-model实现原理

时间:2022-09-28 08:01:03

最近小组有个关于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源码分析&lpar;二&rpar; &colon; 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&period;0&period;3 源码分析Sizzle引擎解析原理

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

  4. Vue源码分析&lpar;一&rpar; &colon; new Vue&lpar;&rpar; 做了什么

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

  5. vue 快速入门 系列 —— 侦测数据的变化 - &lbrack;vue 源码分析&rsqb;

    其他章节请看: 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. IIS部署ASP&period;NET常见错误

    今天本地 IIS部署一个.NET Framework 3.5 项目,首先出现一个错误: 静态机制没有办法处理脚本 检查MIME没有问题,检查应用程序池版本,2.0, 果断改成 4.0. 运行之后新错误 ...

  2. Lumen框架搭建指南

    新人从java转php,到新公司搭建lumen框架,lumen官方文档的坑不是一般的多,对新手极其不友好,记录下我搭建过程,希望对小白们有所帮助. 首先看下官方文档:https://lumen.lar ...

  3. LeetCode 695 岛屿的最大面积

    题目: 给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被水包围着. 找到给定的二 ...

  4. SeaweedFS上手使用指南

    SeaweedFS是基于go语言开发的高可用文件存储系统,主要特性 1.成存储上亿的文件(最终受制于你的硬盘大小)2.速度快,内存占用小 上手使用比fastDFS要简单很多,自带Rest API. S ...

  5. TensorFlow &lpar;RNN&rpar;深度学习 双向LSTM&lpar;BiLSTM&rpar;&plus;CRF 实现 sequence labeling 序列标注问题 源码下载

    http://blog.csdn.net/scotfield_msn/article/details/60339415 在TensorFlow (RNN)深度学习下 双向LSTM(BiLSTM)+CR ...

  6. &commat;Html&period;Display &commat;Html&period;LabelFor &commat;Html&period;EditorFor Html&period;DisplayForModel Html&period;LabelForModel Html&period;EditorForModel

  7. c&num;设计模式之装饰器模式&lpar;Decorator Pattern&rpar;

    引子 在面向对象语言中,我们常常会听到这样一句话:组合优于继承.那么该如何去理解这句话呢? 下面我将以游戏装备为模型用简单的代码去展示它 先创建一个装备的抽象类,然后创建刀枪2个具体的业务子类 pub ...

  8. 二、spark SQL交互scala操作示例

    一.安装spark spark SQL是spark的一个功能模块,所以我们事先要安装配置spark,参考: https://www.cnblogs.com/lay2017/p/10006935.htm ...

  9. &lbrack;置顶&rsqb; 安卓弹出ProgressDialog进度框之后触摸屏幕就消失了的解决方法

    安卓在4.0之前对话框都是模态的,之后就改成非模态了. 解决方法吗,使用progressdialog.setCancelable(false)也行,但是这样就不能响应返回键的事件了,最好的方法是调用p ...

  10. Linux 构建ftp服务器

    1.安装vsftpd服务器 $sudo apt-get install vsftpd 2.cd 到etc文件,配置vsftpd.conf文件 $sudo vi /etc/vsftpd.conf 修改至 ...