原因:     

由于互联网风波,最近也在面试,途中遇到的相对多的问题,也是难点的就是vue底层原理,对于只会用但是不懂得小白来说真是太痛苦了,仅仅能说出来 一些 数据劫持双向数据绑定,虚拟dom树的名词来说远远不够。

 

成果:

花费一天时间看了源码,文档,视频解析。最终得出以下的个人见解,框架高手就可走了,让我们这些拧螺丝的人互相慰藉吧!

 

首先,你需要知道的是,vue实现过程是一个相当简单且很无脑的东西。它分为2个步骤

1、初始化页面与绑定数据

2、更新数据(单向or双向)

 

接下来具体说:

一、初始化数据

在这一部分你需要知道的是:Object.defineProperty 、 nodeType 、document.createDocumentFragment 这三个东西

 

Observe:

Object.defineProperty : 可以用这个方法可以定义一个对象假设obj的属性,如果写了get\set那么这个属性是不可以通过 obj.xxx 修改的

 
vue就是用了这个原理实现的数据劫持数据代理,先说代理

this.msg = 'xxx' 在你的方法里这样写,和 vm=new Vue() ------>  vm.msg='xxx' 一样的,这个无可厚非,但是其实它是被代理的,因为它用了get、set这两个方法,实现的过程其实是 this.msg = 'xxx'  ----> this._data.msg = 'xxx' 其中这个引人注目的 _data就是罪魁祸首了,vue中操作的都是它。也就是说白了 : 你的data 都经过处理了 每一个都有其对应的_data

代理仅仅是让你的this.XXX  = this._data.xxx 并不能实现数据绑定 也就说,想要绑定数据,还需要在对_data再一次的defineProperty

原因很简单,你触发的所有更改属性和更改值都在一个叫做 Compile方法中

Compile:

该方法,结合了nodeType 、document.createDocumentFragment ,一个是节点的类型、后面是文档流碎片,可以理解为虚拟的,不可见的 dom结构,当然这个东西需要创建。过程是这样的:
 

  1. 创建fragment
  2. 将dom(el:‘’#app”)里的所有内容放到里面去
  3. 遍历整个树,找到你的v- 标签 和{{}}这两种表达式 分别替换你设置的data
  4. 把整个结构,在一次替换到真实的dom中 用 appendchild
  5. nodeType:一个数字用来区分遍历的是个啥? document:0\element:1\attriubuite:3\text:4......等等然后做对应的操作

到这一步,初始化数据还差关键的一步 添加watcher和dep

watcher and Dep

  1. 这是一组很简单的 发布订阅模拟,你中有我,我中有你,是多对多的形式
  2. dep是用来沟通watcher 让他渲染的类其中: 一个属性就有一个dep,如果是 a.b 那么就是2个dep
  3. watcher 是对这个表达式的监听类 其中:一个watcher表示 在文档中 这个表达式出现的次数
  4. 这两个分别是在 初始化data和刚才遍历fragment时注册的 
  5. 当页面刷新完成后,这些都做好了,也就实现了第一步,初始化页面并绑定数据与视图的关系

 

二、数据改变(数据驱动)

仅仅就是利用了watcher and Dep举个例子:

一个老师类 可以有多个学生类,那么老师类 里就有一个数组叫 mystudents [new student,new student,newtudent]
里面都是学生,然后 老师有一个方法叫做 “做作业!”那么就会遍历所有学生,去实现 每个学生的 做作业方法


同理,Dep中 也就是属性的改变 会告诉所有 watcher,这几个watcher 是都一样的,只是在页面出现了多少次,去更改值吧!

<div v-html="msg">
<p>{{msg}}</p>

msg一旦变化,就会触发 最开始那个数据 _data.msg中的 set方法 ,然后就会让 所有 msg的watcher都会改变,但是,这个v-text 和 msg具体的 改变不同了,一个是innerHTML下面是 textContent都是替换而已 

watcher是通过callback 实现了 解析 文档流时候的 update方法 其实不用管是怎么改变的,你只需要知道,是通过了

this.mgs = 'xxx'------>observe(先触发的set方法,在方法里有dep)----->Dep----->Wather----->update 的过程

双向数据绑定

v-model 在源码中与其他标签属性的解析一样,只是多了一个 监听事件 input,再次触发的时候,在一次的改变dep,watcher,最后在通过watcher 里的update方法 更新了视图

所以,vue其实是单向的,并没有什么双向的驱动

 

学习来源:https://github.com/DMQ/mvvm/tree/master/js

 

Logo

前往低代码交流专区

更多推荐