热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

vmodel双向绑定原理_【Vue原理】VModel白话版

专注Vue源码分享,为了方便大家理解,分为了白话版和源码版,白话版可以轻松理解工作原理和设计思想,源码版可以更清楚内部操作和
18e7b69089558ec4762ce5ec581c1c78.png
专注 Vue 源码分享,为了方便大家理解,分为了白话版和 源码版,白话版可以轻松理解工作原理和设计思想,源码版可以更清楚内部操作和 Vue的美,喜欢我就关注我的公众号,公众号的文章,排版更好看

如果你觉得排版难看,请点击下面链接 或者 关注公众号

【Vue原理】VModel - 白话版​mp.weixin.qq.com
1eebceec35f9882e917449c4c61de94a.png

说到 Vue,感觉第一印象就是双向绑定,所以v-model键值是Vue印象的半壁江山啊,这么重要的东西,你好歹要知道是怎么实现的吧

我们今天就来讲解双向绑定的工作原理,你应该知道,双向绑定就是通过绑定 dom 事件来实现的,可是,怎么绑定的事件,绑定什么事件?

首先,双向绑定,我个人认为应该分为 初始化绑定双向更新 两part。

初始化绑定,就是初始化时给表单元素绑定值,绑定事件,为双向更新做准备

双向更新,就是任意一边变化,同时能让另一个边更新

双向更新那是后话,只有一开始时成功执行绑定操作才会有之后 双向更新这个东西,所以,今天按顺序来了解两个part,从四个问题开始

1、v-model 怎么给表单绑定数据

2、v-model 绑定什么事件

3、v-model 怎么绑定事件

4、v-model 如何进行双向更新

TIP

v-model 还可以用在 自定义组件上,但是很明显,这次我们先不讲这一块,而是先将正常的表单使用

8af2042877e6826143185fb36690fce9.png

先看结论

我们先以 input text 类型讲解,对于其他的表单元素,流程都差不多,只是中间涉及的内容不同。所以就先讲个例子,然后具体在源码版全部一起说

1、怎么赋值?v-model 绑定的数据赋值给表单元素的 value 属性

2、怎么绑定事件?解析不同表单元素,配置相应的事件名和事件回调,在插入dom之前,addEventListener 绑定上事件

3、怎么双绑?外部变化,触发事件回调,event.target.value 赋值给model绑定的数据;内部变化,修改表单元素属性 value

看完结论,有点懵?我们来看看具体的内容,结果导向来进行学习

下面的讲解以下面这个为例

ecdedc0273fc3bb730d31b18b7d52270.png
1d988cf254a377185ebb6a06e067cce4.png

v-model 怎么给表单绑定数据

获取值流程

首先,上面例子解析后的渲染函数是下面这样(已简化,只保留表单值相关)

(

1、这个渲染函数是没有执行的 匿名函数。执行的时候,会绑定上下文对象为 组件实例

2、于是 with(this) 中的 this 就能取到 组件实例本身,with 的代码块 顶层作用域 就绑定为了 组件实例

3、于是 with 内部变量的访问,就会首先访问到 组件实例上。其中 name 的 获取,就会先从 组件实例上获取,相当于 vm.name。赋值完成后,domProps 就是下面这样

{

4、上面的 value 是 v-model 解析成的原生属性,保存在属于该节点 input 的 domProps 对象存储器中

绑定值流程

创建dom input 之后,插入dom input 之前,遍历该 input 的 domProps ,逐个添加给 input dom

简化后的代码像下面这样进行赋值

for

其中给节点赋值就是这样

input

8af2042877e6826143185fb36690fce9.png

v-model 绑定什么事件

不同的表单元素使用v-model,会绑定不同的 事件

change 事件

select,checkbox,radio

input 事件

这是默认事件,当不是上面三种表单元素时,会解析成 input 事件

比如 text、number 等 input 元素和 textarea

TIP

实际上关于 input 和 textarea 绑定的事件远不止 input 一个事件,但是涉及内容太多,打算放在源码版说明,这里先简单默认是 input 事件

8af2042877e6826143185fb36690fce9.png

v-model 怎么绑定事件

上面例子解析成下面的渲染函数(已简化,只保留事件相关)

with

解析事件流程

1解析不同表单元素,配置不同的事件

2拼装 事件回调函数,不同表单元素,回调不一样

3把 事件名和拼装回调 配套 保存给相应的表单元素的 on 事件存储器

什么时候绑定事件

生成 input dom 之后,插入input dom 之前

怎么绑

使用之前保存的 事件名和 事件回调,给 input dom 像下面这样绑定上事件

input

8af2042877e6826143185fb36690fce9.png

v-model 如何进行双向更新

双向,指的是 外部和内部

外部变化:用户手动改变表单值,输入或者选择

内部变化:从内部修改绑定值

内部变化

1、v-model 绑定了 name ,name 会收集到 本组件的 watcher

a. 下面渲染函数执行时,会绑定本身组件实例为上下文对象

b. name 访问的是 组件实例的 name

c. name 此时便收集到了 当前正在渲染的组件实例,当前渲染的实例是自己,于是收集到了自身的 watcher

(

如果你不懂 收集 watcher 什么意思,建议看下我的另一篇文章

【Vue原理】响应式原理 - 白话版

2、内部修改 name 变化,通知收集器内的 watcher 更新,所以本组件会更新,上面的渲染函数重新执行,便 重新从实例读取 name

c6ebb0711ebb4a63cbc9a762c291adc8.png

3、重新给 input dom 的 value 赋值,于是 页面就更新了

怎么赋值?那是回到第一个问题了,兄弟

外部变化

手动改变表单,事件触发,执行事件回调(下面这个),更新组件数据 name

function

更新内部数据流程

1、当事件触发的时候,会把 表单的值 赋值给 name

2、name 是从 组件实例上访问的

3、所以这次赋值会 直接改变组件实例的 name

回调怎么赋值给组件实例的name?

一开始不懂,所以不理解,也没查到,写了个例子,大概理解了意思

1、因为事件回调 在 with 里面声明

2、于是事件回调的 作用域链最顶层 就加上了一层 with 绑定的作用域

3、就算事件回调不在 with 中执行,事件回调中的 变量访问,也会先访问之前 with 绑定过的作用域,因为作用域链的最顶层

with举栗子

var

你认为 fn 执行的时候,会打印出什么呢?行了,给你看结果了

3d3084ea2c4ed56ff843f5ade542666f.png

好吧,再一次深刻认识到一个知识点,with 绑定作用域原来这么强,离开with执行,还是先访问他的作用域,脱离不出魔爪啊,强盗作用域

87e354f77e9fba0ae36122d6ad06fac1.png

回来总结!

于是当事件回调执行的时候,会 直接赋值 给 组件实例的name,这样便通过外部改变了内部数据

TIP

外部变化,本来可能会存在一种情况

a、手动修改表单后, 回调内会更新组件的值

b、组件的值更新之后,会通知组件更新,组件更新时,便又会重新把input 赋值一遍

非常多余的一步操作,所以这里,Vue做一个判断,判断旧值和 新值是否相等,不等才更新,关于旧值,会保存在 dom 的 _value 属性

8af2042877e6826143185fb36690fce9.png

总结

v-model 三要素

1、绑定属性

2、绑定事件

3、属性+事件组合完成双向更新

8af2042877e6826143185fb36690fce9.png

历史分享

【Vue原理】Vue源码阅读总结大会 - 序

【Vue原理】学会调试Vue源码

【Vue原理】响应式原理 - 白话版

【Vue原理】Props - 白话版

【Vue原理】月老Computed - 白话版

【Vue原理】Watch - 白话版

【Vue原理】Mixin - 白话版

【Vue原理】Methods - 源码版

【Vue原理】Filters - 源码版

8af2042877e6826143185fb36690fce9.png

最后

希望你认真阅读后,能豁然开朗。如果你懂了,我的目的也达到了,如果你还不懂,可以留言告诉我哦,百分百回复好吧

当然如果本文有任何描述不当的问题,欢迎后台联系本人,重谢

如果你认为有帮助的,谢谢点个赞。如果写得不对的地方,可以骂我

f717f44afe0fafce1e0895268f38e36e.png



推荐阅读
  • 点击后defaultEducation的值明明改变了,但props传给子组件却watch不到 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • Ihavethefollowingonhtml我在html上有以下内容<html><head><scriptsrc..3003_Tes ... [详细]
  • 网址:https:vue.docschina.orgv2guideforms.html表单input绑定基础用法可以通过使用v-model指令,在 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • 有几百条数据类似*Oct1809:46:09:%NFPP_IP_GUARD-4-DOS_DETECTED:Host<IP60.12.174.45,MACNA,portGi2 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • javascript  – 概述在Firefox上无法正常工作
    我试图提出一些自定义大纲,以达到一些Web可访问性建议.但我不能用Firefox制作.这就是它在Chrome上的外观:而那个图标实际上是一个锚点.在Firefox上,它只概述了整个 ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 相关的部分代码如下 ... [详细]
author-avatar
北路新华
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有