深入Vue3学习(4),vue源码学习,实现miniVue

真实DOM渲染

以前写html的时候都是直接编写Html代码然后浏览器解析成dom树,再渲染到页面

虚拟DOM的优势

很多框架都会引入虚拟dom对真实的dom进行抽象,有很多好处

其一: 可以对真实的元素节点进行抽象,抽象成vNode,方便后续进行各种操作,因为直接操作DOM是有很多限制的,比如diff算法,clone的,而vnode是一个虚拟节点,也就是一个对象,在虚拟节点上可以使用js来操作这些,非常方便,比如对虚拟节点进行diff算法就比dom上方便很多。(虚拟节点可以通过js进行很多方便的操作)
跨平台

可以将vNode节点渲染成各种想要的节点,比如ios,android,web这些。比如在ios上开发,可以将vnode通过其他方式转化成ios开发的一些控件(跨平台开发方便)

虚拟dom渲染过程

单个节点:templage =>render函数=>返回vnode=>通过渲染器展示为真实的html元素=>浏览器展示。
多个节点:templage=>render=>vnode=>组成虚拟dom=>真实dom

三大核心系统

vue的源码包含三大核心:
一:complier模块,编译模板系统
二:runtime模块,也成为render模块,真正渲染的模块
三:reactvivtiy:响应式系统

实现mini-vue

主要实现三个功能

一 渲染系统模块
二 可响应式系统模块
三 应用程序入口

渲染系统模块(三个功能)

1 h函数,返回一个vnode对象
2 mount函数,将vnode怪载到dom
3 patch,用于将两个vnode进行diff算法,决定如何处理新的vnode。
在这里插入图片描述
先实现两个,一个vnode,一个mount
在这里插入图片描述
h函数还是简单的。

mount函数主要做三个事情,

通过传入的vnode创建新的element,处理第二个参数props,处理第三个参数children,将创建的element挂载到container上。

  //通过mount ,将vnode挂载到#app上
      mount(vnode, document.getElementById("app"));

在这里插入图片描述

大概形状,接着看具体实现:
在这里插入图片描述
处理Porps要注意事件的处理
在这里插入图片描述
children假设只能传string和array。
如果children是array,表示有其他的h函数,子节点是dom节点,所以再次调用mount递归即可。

效果:

在这里插入图片描述

在这里插入图片描述

3 patch函数的实现(简单实现,没有key)

分为几个流程
1 判断是否同一节点
2 处理同一节点的props
3 处理children
在这里插入图片描述
对新节点的处理
在这里插入图片描述
对老节点的处理
在这里插入图片描述
新节点是字符串的处理
在这里插入图片描述
新老节点都有children并且换位diff算法处按
在这里插入图片描述

响应式系统(发布-订阅模式)

思路: 创建Dep类用来创建每一个订阅者,创建watch函数来收集依赖,创建一个reactiveh函数来劫持对象。通过劫持的get和set分别收集对应的依赖以及更新各个订阅者。
Dep类
在这里插入图片描述
创建watch函数来收集依赖
在这里插入图片描述
创建一个getMap函数来管理Dep集合
在这里插入图片描述

reacitve函数的实现
vue2的实现
在这里插入图片描述
通过get方法来收集依赖,通过set方法来触发每个订阅者的notify方法来调用。
vue3的实现
在这里插入图片描述
这样简单的响应式系统的处理好了,当每次使用watchEffect加入依赖的时候会先调用一次函数,那个函数会触发劫持的get方法,然后将该函数加入到特定的dep对象的依赖中,通过getMap函数来管理每个对象每个属性的dep。因为每个属性都有一个订阅者。当值修改的时候,触发set方法来调用dep的notify方法,以此来告诉订阅者值更改了。

createApp的实现

在这里插入图片描述
我们只需要收集进依赖就行了,里面的函数会先执行一次,第一次时mount,第二次则是patch进行比对。
在这里插入图片描述
在这里插入图片描述
当调用createApp的时候收集依赖,当btn触发的时候,会劫持get方法,将该依赖放到Dep中,然后更改值,劫持set方法,调用notify,它会将依赖函数再执行一次,也就是patch(old, new)而这时候的this.data.counter已经改变了,所以会通过patch函数反馈到ui上,达成响应式。

为什么vue3选择proxy呢?

1 首先 vue2的Object.defineProperty在劫持对象的属性时,需要递归调用fefinedProperty去监听。,而Proxy劫持的是整个对象,不需要做特殊处理。而且defineProperty对属性的删除和新增是无法监听的,因为他是对属性的监听,新增属性他舰艇不了。所以vue2提供了像$set来增加对对象的属性劫持。
2 修改的对象不同,
使用defineProperty的时候,修改原来的obj就可以触发拦截,而proxy则必须修改代理对象,proxy的实例才会触发拦截。
3 proxy能观察的类型比defndProperty更丰富
has: in操作符的俘获器
deleteProperty: delete的俘获器

4 Proxy作为es6新特性标准,关注性会更高
缺点: Proxy不兼容iE,也没有一些profill。而defineProperty能支持到IE9

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderlin_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值