前言
本文章结合VUE核心技术-尚硅谷的49-55集做的归纳总结。
数据代理准备
1.通过一个对象代理对另一个对象中属性的操作(读/写)
2.通过vm对象来代理data对象中所有属性的操作
3.好处: 更方便的操作data中的数据
4.基本实现流程
1). 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符
2). 所有添加的属性都包含getter/setter
3). 在getter/setter内部去操作data中对应的属性数据
vm实例中有 _data 数据,存储了Vue初始化的数据。
name属性则是动态属性,需要在控制台点击获取
点击其实是执行了 name 的 get 方法,这个就是代理
set方法就是当值发生改变的时候执行
浏览器 Debug 调试
浏览器的控制台上 Source 标签提供了 断掉调试模式
方便追踪代码的运行情况。
浏览器上如上图的有四个按钮用来进行代码测试
- 第一个按钮,开启断点调试或跳到下一个断点
- 第二个按钮,执行下一行
- 第三个按钮,执行到下一个函数
- 第四个按钮,跳出当前函数
浏览如上图的位置可以切换控制台的摆放方式
右边可以看到当前断点运行的位置,还可以看到是什么文件以及第几行代码
如此点击第二个按钮就可以一行一行执行代码,可以看到变量属性在执行代码之后的变化。
数据代理分析
此处遍历data的所有数据,并执行代理函数
代理函数执行 defineProperty 到 vm 对象上
这样就完成了所有数据代理,实现数据获取和更新
1 | /* |
模板解析
1.模板解析的关键对象: compile对象
2.模板解析的基本流程:
1). 将el的所有子节点取出, 添加到一个新建的文档fragment对象中
2). 对fragment中的所有层次子节点递归进行编译解析处理
* 对表达式文本节点进行解析
* 对元素节点的指令属性进行解析
* 事件指令解析
* 一般指令解析
3). 将解析后的fragment添加到el中显示
3.解析表达式文本节点: textNode.textContent = value
1). 根据正则对象得到匹配出的表达式字符串: 子匹配/RegExp.$1
2). 从data中取出表达式对应的属性值
3). 将属性值设置为文本节点的textContent
4.事件指令解析: elementNode.addEventListener(事件名, 回调函数.bind(vm))
v-on:click="test"
1). 从指令名中取出事件名
2). 根据指令的值(表达式)从methods中得到对应的事件处理函数对象
3). 给当前元素节点绑定指定事件名和回调函数的dom事件监听
4). 指令解析完后, 移除此指令属性
5.一般指令解析: elementNode.xxx = value
1). 得到指令名和指令值(表达式)
2). 从data中根据表达式得到对应的值
3). 根据指令名确定需要操作元素节点的什么属性
* v-text---textContent属性
* v-html---innerHTML属性
* v-class--className属性
4). 将得到的表达式的值设置到对应的属性上
5). 移除元素的指令属性
双大括号表达式
compile函数会获取绑定 el 对象,如果没有则获取 body 对象上
检查传入的对象是不是元素节点,如果不是元素则通过 querySelector 来获取元素,H5添加了类似JQuery选择器的功能
将node节点转换为 fragment 容器
正如之前 fragment 演示的一样,会将页面的内容截取掉。
下一步就会执行 init 函数
init函数会执行
compileElement
函数
compileElement
内部会获取 fragment 获取到的节点
然后将数组转为真数组进行遍历
通过正则表达式来匹配 双大括号
isElementNode 可以过滤 div 等等 Html 节点
然后继续进入子对象,就会获取到 div 中的内容
如果检测是 文本信息 就通过上面的正则表达式进行匹配,由于正则表达式加入了括号,获取的内容会放到 $1 变量中
这个正则表达式非常好用,Vscode编辑器也是一样的
鼠标指向可以看到 $1 存储了name数据
这里会进入到 compileUtil 工具集
可以看到这个工具集函数定义了很多相关的方法
执行工具集会跳转到 bind 方法,bind中使用了 updater 相关函数
updater也有很多设置好的更新方法
通过 [] 传值,动态获取updater中的函数
如果 updaterFn 不存在就不执行,如果存在执行函数
_getVMVal 返回
vm._data
对象中的数据
同时拆分了传入的变量 exp 中的内容
最后将返回的值赋值到 textContent 上,完成了内容的更新
事件指令
在HTML中添加按钮绑定点击事件
在节点解析的过程中会进入到相关属性的处理
在这里遍历标签上的属性
判断指令是否是 directive 指令,就是判断是否含有 v-
然后截取后两个字符的字符串
判断是不是事件指令 (‘on’ 开头)
然后进入 eventHandler 函数
截取 : 获取事件名
从 methods 中获取传入的事件
如果时间名和函数同时存在,就执行 addEventListener
fn.bind(vm) 可以让函数的 this 指向 vm
一般指令
修改HTML标签
普通指令的执行会获取到 dir 的 text 属性
然后会执行到 compileUtil 的 text 函数
再接着执行 bind 函数
updater 里面通过 textContent 更新页面内容
通过 innerHtml 实现 HTML 标签的渲染
class的更新稍微复杂一点,需要和原有的class进行合并
点击第五个按钮可以禁用 所有的断点
1 | function Compile(el, vm) { |