最近被裁了😂,正好有大把时间来深入一下Vue源码了,笔者开发是主React,副Vue的,可能出现错误敬请谅解。
作为任务的开始,我们先来了解一些常见基础概念。
编程范式
编程范式分为:
命令式:关注过程的一种编程范式,描述了完成一个功能的详细逻辑和步骤,当项目越复杂,描述难度越大声明式:关注结果的一种编程范式,并不关心完成一个功能的详细逻辑与步骤
声明式 VS 命令式
性能:命令式>=声明式可维护性:声明式>=命令式
.vue中的html如何转化
- 编译时:
compiler:把html的节点,编译成render函数 - 运行时:
runtime:利用render把vnode渲染成真实dom节点 - 运行时+编译时:
runtime+compiler
vue通过
compiler解析html模板,生成render函数,然后通过runtime解析render,从而挂载真实dom
为什么vue要设计成一个 运行时+编译时的框架
首先要理清dom渲染是如何进行的,可以分为两部分: - 初次渲染,可以叫做挂载 - 更新渲染,可以叫做打补丁
初次渲染
什么是初次渲染呢? 假如有如下节点:
<div id='app'></div>
这时节点的innerHTML为空,我们在该div中渲染如下节点:
<ul>
<li>1</li>
<li>2</li>
</ul>
最后结果为:
<div id='app'>
<ul>
<li>1</li>
<li>2</li>
</ul>
</div>
此时就是初次渲染
更新渲染
更新渲染即,初始状况为上一步的结果时,假如我们需要对li进行更改,更改玩,就会发生浏览器渲染,这就是更新渲染。
但是浏览器更新渲染也会出现两种方式:
- 删除所有的节点,重新渲染新的节点
- 删除原位置的节点,在新位置插入
第一种是不做任何比较,直接进行:这会涉及到更多的DOM操作,更耗时
第二种会进行比较,只对需要更改的节点起作用,其他节点不变:这会涉及到js计算+少量的dom操作
答:
- 针对
纯运行时,因为不存在编译器,所以只能提供一个复杂的JS对象 - 针对
纯编译时,因为缺少运行时,所以只能把分析差异的操作,放到编译时运行,同样因为省略了运行时,所以速度可能会更快,但是这将损失灵活性,比如svelte,他就是一个纯编译时的框架,但是他的实际运行速度可能达不到理论上的速度 运行时+编译时:比如 Vue或React都是通过这种方式来构建的,使其可以在保持灵活性的基础上,尽量进行性能的优化,从而达到一种平衡
什么是副作用
副作用:当我们对数据进行setter或getter操作时,所产生的一系列后果
Vue中的响应核心依赖于setter和getter,即赋值和取值行为能够产生副作用
Vue3基本框架设计
核心三大模块:
- 响应性:
reactivity - 运行时:
runtime - 编译器:
compiler
根据结构阐述
<template>
<div>
{{proxyTarget.name}}
</div>
</template>
<script setup>
import {reactive} from 'vue';
const target={
name:'伯nulee'
}
const proxyTarget=reactive(target)
</script>
对于响应性而言:上面代码响应性暴露出reactive函数,可以接收一个复杂数据类型作为被代理对象,返回一个代理对象,当proxyTarget触发setter和getter行为的时候,都会产生对应的副作用
编译器:对于编译器而言,是把模板即template中代码编译成render函数
运行时:把compile编译器返回的render函数进行调用从而渲染成真实dom