mvvm vue 实现原理 介绍

原文链接: mvvm vue 实现原理 介绍

上一篇: mvvm defineProperty 设置 对象属性

下一篇: mvvm oop 实现

7326b04e5f292d02c61073b548a7b1db974.jpg

实现原理

1. Vue作为一个MVVM框架的基本实现原理:数据代理、模板解析、数据绑定
2. Vue涉及的核心技术:虚拟DOM、Diff算法
3. 关键性方法:Object.defineProperty(obj, prop, descriptor)

DocumentFragment

1. DocumentFragment:文档碎片,虚拟DOM对象,表示一个没有父级文件的最小文档对象;
2. 被当作一个轻量版的Document使用,用于存储已排好版的或尚未打理好格式的XML片段;
3. Document对应显示的页面,包含N个Element,更新Document内部的元素,界面也会更新;
4. DocumentFragment并不是真实DOM树的一部分,而是内存中保存N个Element的容器对象,
不与界面关联,它的变化不会引起DOM树的重新渲染,界面不变,且不会导致性能等问题;

数据代理

1. 数据代理:通过一个对象代理操作另一个对象中的属性;
2. Vue的数据代理:通过vm对象来代理data对象中的所有属性操作;
3. Vue数据代理的实现:vm中的_data属性代理了data对象
    1. 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符,监视
    vm的属性变化;
    2. Object.defineProperty()会为vm中所有添加的属性提供getter/setter,它们内部
    去操作data中对应的属性数据。
数据代理: 通过一个对象代理对另一个对象中的属性的操作(读/写)
vue数据代理: 通过vm对象来代理data对象中所有属性的操作
好处:更加方便的操作data中的数据
基本实现流程:
    通过Object.defineProperty给vm添加与data对象的属性对应的属性值描述符
    所有添加的属性都包含getter和setter
    getter和setter内部去操作data中对应的属性数据

模板解析

1. 创建DocumentFragment对象,递归遍历DOM树,将DOM节点添加进DocumentFragment中,
也即,将DOM节点映射到虚拟DOM对象中;
2. 解析大括号表达式({{name}})、一般指令、事件指令。
模板更新

模板更新的基本流程
1,将el的所有子节点取出,添加到一个新的文档fragment对象中
2,对fragment中所有层次子节点递归进行编译解析处理
    对大括号表达式文字结点进行解析
    对元素节点的指令属性进行解析
        事件指令解析

大括号表达式解析
根据正则表达式对象得到匹配出的表达式字符串
从data中取出表达式对应的属性值
将属性值设置为文本结点的textContent


事件指令解析
从指令名中取出事件名
根据指令的值(表达式)从methods中得到对应的时间处理函数对象
给当前元素结点绑定指定事件名和回调函数的dom时间监听
指令解析完后,移除此指令属性


一般指令解析
得到指令名和表达式 text/html/class
从data中根据表达式得到对应的值
根据指令名确定需要操作元素结点的什么属性
    v-text ==> textContent
    v-html ==> innerHtml
    v-class ==> class
将得到的表达式的值设置到对应的属性上
移除元素的指令属性

数据绑定

1. 一旦更新了data对象中的某个属性数据,所有界面上直接/间接使用此属性的节点都会更新;
2. 数据劫持:Vue中用来实现数据绑定的一种技术;
3. 劫持的基本思想:也是通过Object.defineProperty()为data对象中的属性添加setter/
getter,来监视所有属性数据的变化,并随之更新界面;
4. vm --> data --> 更新界面
5. 双向数据绑定:建立在单向数据绑定的基础之上;
    1. 在解析v-model指定时,给当前元素添加input监听;
    2. 当input的value发生变化时,将最新的指赋给当前表达式对应的data对象中的属性。

数据绑定
一旦更新了data中的某个属性数据,所有界面上直接使用或者间接使用此属性的结点都会更新


数据劫持
数据劫持是vue中用来实现数据绑定的一种技术
基本思想:通过defineProperty来监视data中的所有属性(任意层次)
一旦变化就去更新界面

四个对象

Observer
    用来对data所有属性数据进行劫持
    给data中所有属性重新定义属性描述符(get/set)
    为data中的每个属性创建对应的dep对象

Dep(Depend)
    data中的每个属性(所有层次)都对应一个dep对象
    创建的时机:
        在初始化definedata中各个属性时创建对应的dep对象
        在data中的某个属性值被设置为新的对象时
        当watcher被创建时,内部将当前watcher对象添加到对应的dep对象的subs中
        当此data的属性值发生改变时,subs中所有的watcher都会收到更新的通知,从而更新对应的界面

Compiler
 用来解析模板页面的对象
 利用compile对象解析模板页面
 每解析一个表达式(非事件指令)都会创建一个对应的watcher对象,并建立watcher与dep的关系
 compile与watcher关系:一对多的关系

Watcher
    模板中每个非事件指令或者表达式都对应一个watcher对象
    监视当前表达式数据的变化
    创建的时机:在初始化编译模板时






Dep
    实例什么时候创建
        初始化给data属性进行数据劫持时创建的
    个数
        与data中的属性一一对应
    Dep的结构
        id:标示
        subs:[] n个相关的watcher的容器(数组)


Watcher
    实例什么时候创建
        初始化的解析大括号表达式/一般指令时创建
    个数
        与模板中的表达式(不包含事件指令)一一对应
    Watcher结构
        cb ==> 回调函数,用于界面更新
        vm ==> vm实例
        exp ==> 对应的表达式
        depIds ==> {} 相关的n个dep容器对象
        value ==> 当前表达式的对应value

Dep 与Watcher的关系
    什么关系:
        多对多
        data属性 ==> Dep ==> n个watcher(模板中有多个表达式使用了此属性)
        表达式 ==> watcher ==> m个Dep (多层表达式a.b.c)

    如何建立
        data中属性的get()中建立
    什么时候建立
        初始化的解析模块中的表达式创建watcher对象时

    在dep 创建完成后,创建watcher时再建立关系

双向数据绑定

双向数据绑定
双向数据绑定时建立在单向数据绑定(model==>view)的基础之上的
双向数据绑定的实现流程
    在解析v-model指令时,给当前元素添加input事件监听
    当input的value发生变化时,将最新的值赋值给当前表达式所对应的data属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值