深入Vue3学习,vue源码学习,实现miniVue
Posted lin_fightin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入Vue3学习,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劫持的是整个对象,不需要做特殊处理。所以vue2提供了像$set来增加对对象的属性劫持,因为defineProperty的时候对新增的属性是不会劫持的。
2 修改的对象不同,
使用defineProperty的时候,修改原来的obj就可以触发拦截,而proxy则必须修改代理对象,proxy的实例才会触发拦截。
3 proxy能观察的类型比defndProperty更丰富
has: in操作符的俘获器
deleteProperty: delete的俘获器
…
4 Proxy作为es6新特性标准,关注性会更高
缺点: Proxy不兼容iE,也没有一些profill。而defineProperty能支持到IE9
以上是关于深入Vue3学习,vue源码学习,实现miniVue的主要内容,如果未能解决你的问题,请参考以下文章