vue3 框架学习概念笔记

news2024/9/23 7:27:05

文章目录

  • 前情提要
  • 框架设计概览
    • 命令式
    • 声明式
      • 小结
    • 虚拟dom性能
    • 运行时和编译时
    • 框架设计核心要素
    • 声明式描述UI
    • 渲染器
    • 组件的本质
    • vue.js模板
  • 响应式系统
    • 概念
    • 完善的响应式系统
    • 响应式系统的调度
    • 计算属性Computed
    • watch 原理
    • 竞态问题
    • 非原始值的响应式方案
    • javaScript 对象
    • 原始值的响应式方案
    • ref
    • toRef,toRefs
  • 渲染器
    • 渲染器与响应式系统
    • 自定义渲染器
    • 挂载与更新
    • 简单Diff 算法
    • 双端Diff 算法
    • 快速Diff算法
  • 组件化
    • 描述组件
    • setup函数
    • 异步组件
    • 内建组件和模块
  • 编译器
    • vuejs的模板编译器
    • 解析器
    • 编译优化
  • 服务端渲染
  • 最后

前情提要

在这里插入图片描述
之前在没有接触vue3之前,就买了一本书:vue.js设计与实现 --霍春阳(基于vue3)一直没有时间看,最近几天我看完了整本书,获益颇深,使得我对框架的认识和编写项目时的动作更加得心应手,由此我将记录此书中对于各模块的概览内容,目的如下:

  1. 帮助入门vue开发者对框架概念有一个轮廓
  2. 给自己留下记忆碎片,以便将来使用

这篇文章中我将只会记录概念相关,不涉及代码,如果想结合代码学习,我推荐前往阅读 vue.js设计与实现 --霍春阳 这本书,霍前辈在书中的样例思路清晰,代码逻辑严密,阅读此书,会有一次js高级编程的体验;


框架设计概览

命令式

jquery就是典型的命令式框架,通过执行各种链式函数完成动作,其一大特点是关注过程–做事的过程;

声明式

声明式框架会更加关注结果,过程交由框架完成,例如vue.js的内部实现一定是命令式的,而暴露给用户的却更加声明式;

小结

vue是内部封装了命令式代码才完成了面向用户的声明式,所以声明式代码的性能不优于命令式代码的性能,但是却带来了极高的可维护性,而vue框架要做的就是在保持可维护性的同时,使性能损失最小;

虚拟dom性能

操作dom的方式有三种,原生js,虚拟dom,innerHTML, 不可以简单下定论,如结合维护性,心智负担,更新策略来看,虚拟dom是很好的选择;

运行时和编译时

三种框架设计选择

  1. 运行时:不分析内容来源,提供固定功能
  2. 编译时:分析用户提供的内容,做相应处理,有损灵活
  3. 运行时+编译时:vue3使用的架构模式

框架设计核心要素

  1. 友好的警告信息(问题位置)
  2. 控制生产环境体积 (Tree-Shaking)
  3. 良好的兼容性 (对象式API,组合式API),用户可以通过特性开关,从而利用Tree-Shaking 机制排除
  4. 使用TS编写框架和对TS类型支持友好是俩件事,支持ts需要花费额外的精力;

声明式描述UI

直接使用虚拟DOM描述UI,用户不需要关注过程;

渲染器

把虚拟DOM对象渲染为真实DOM对象,实现方式是递归遍历虚拟DOM对象,并调用原生DOM-API 完成真实DOM创建,其精髓在于后续的DIFF算法;

组件的本质

一组虚拟DOM元素的封装,可以是一个返回的虚拟DOM函数,也可以是一个对象,但这个对象下必须要有一个函数用来产出组件要渲染的虚拟DOM

vue.js模板

vue.js模板会被一个叫做编译器的程序编译为渲染函数;编译器和渲染器都是vue.js的核心部分;


响应式系统

概念

在理解响应式实现原理之前,理解副作用函数更重要,副作用函数就是在执行时会影响其他地方的函数执行,vue.js3 采用proxy实现响应式数据,通过拦截数据的get,和set 方法,这个过程需要清晰的思路;

完善的响应式系统

使用WeakMap 配合Map构建了新的桶结构,使响应式数据与副作用函数建立精确的联系;

  1. WeakMap 对象:弱引用,不影响垃圾回收器的工作。当用户代码对一个对象没有引用关系时,WeakMap 不会阻止垃圾回收机制回收该对象。

响应式系统的调度

期望有能力决定副作用函数的执行时机、次数及方式;

计算属性Computed

原理上是一个懒执行的副作用函数,在读取时重新计算其真正的值

watch 原理

利用副作用函数重新执行时的可调度性,当依赖的响应式数据发生变化时,执行effect的调度器函数,即回调;此外,一个立即执行的watch函数通过添加immediate选项来实现,通过flush选项指定回调函数的执行时机,本质上是利用了调用器和异步的微任务队列;

竞态问题

带入场景简单理解就是,watch的回调,存在异步,第二次更新覆盖第一次的回调执行内容;

非原始值的响应式方案

vue.js 3的响应式数据是基于Proxy 实现的,所以有必要理解Proxy及Reflect;

  1. Proxy对象可以创建一个代理对象,从而实现对其他对象的代理,代理指的是对一个对象基本语义的代理,允许我们拦截并重新定义对一个对象的基本操作,其中基本语义可以理解为对一个对象的读取和设置操作;
  2. Reflect对象具有和Proxy同样的方法,其特别之处在于可以接受第三个参数,receiver,即接收者,可以理解为函数调用过程中的this;

响应式的实现不只是简单的拦截get/set内部方法,更有迭代对象的拦截,例如for…in,for…of,set,map,这些具有特征的对象,都需要特别处理;

javaScript 对象

有俩种对象,一种为常规对象,另一种叫异质对象,其区别在于内部的实现方法;

原始值的响应式方案

原始值指的是Boolean、Number、BigInt、String、Symbol、undefined、null等类型,在js中原始值是按值传递的而非引用传递;

ref

ref实质上是一个包裹对象,由于Proxy无法提供对原始值的代理,所以用一层对象包裹,间接实现响应式,这也就是为什么在使用中需要.value;

toRef,toRefs

ref不仅可以用于原始值响应式方案,也能用来解决响应式丢失,这也就是toRef及toRefs出现的理由,toRef是代理一个对象的响应式值,toRefs则是多个,本质上是对响应式数据作的包装,或者叫访问代理,我们知道一般的响应式对象如reactive包裹的对象通过解构后会丢失响应式,那么可以在解构的时候通过toRef函数进行一次代理访问来保持响应式特性。

渲染器

用来执行渲染任务,是渲染真实DOM和跨平台能力的关键,渲染器把虚拟dom渲染为真实dom的过程叫作挂载,通常用英文mount表达。

渲染器与响应式系统

利用响应式系统的能力,可以做到数据编号自动更新页面,渲染器会执行挂载和打补丁操作,对于新内容,会执行挂载,而就内容,会执行打补丁操作,只更新新的node;

自定义渲染器

在浏览器平台,渲染器可以利用DOM API完成DOM操作,为了不直接依赖浏览器,将这些操作封装为可配置的对象,用户可以在调用createRenderer函数创建渲染器的时候自定义配置对象,从而实现自定义的行为;

挂载与更新

在这里我学到了HTML的节点的属性比想象中复杂,其中有俩个重要概念,HTML Attributes 和DOM Properties 并不完全对应,有的属性甚至是只读的,所以vue在属性的挂载上做了足够的工作; vue.js对特殊属性也做了属性增强,例如 class, style ,它们支持 字符,对象,数组 三种数据的格式;

简单Diff 算法

为了减少新旧node节点性能开销,完成更新操作,这个比较的算法就是diff算法,渲染器的核心就是diff算法,试图最大程度的复用DOM元素;简单diff算法的核心逻辑是,拿新的一组子节点中的节点去旧的一组子节点中寻找可复用节点。这个过程中key的作用就像是身份证号,在更新时通过key找到可复用的节点,避免过多的对DOM元素进行销毁和重建。

双端Diff 算法

指的是在新旧俩组子节点的四个端点之间分别进行比较,并试图找到可复用的节点,优势在于执行的DOM移动操作次数更少。

快速Diff算法

在实测中性能最优,借鉴了文本Diff中的预处理思路,先处理新旧俩组节点中相同的前置节点和相同的后置节点,当全部节点处理完毕后,如果无法简单的操作不存在的节点完成更新,会根据节点的索引关系,构造出一个最长递增子序列,其中最长递增子序列指向的节点则是不需要移动的节点。例如[2,8,9,0,3,5,7] 中 最长递增子序列为[0,3,5,7],这一部分对应的索引节点,就可以不去移动,从而提升diff性能;

组件化

组件化的能力可以使一个大模板变成一个个小模板,从而使组件可以组合,组成完整的页面,其核心也需要渲染器支持;

描述组件

利用虚拟节点的vnode.type属性来存储对象,渲染器根据虚拟节点的该属性类型来判断它是否是组件。

setup函数

该函数为了组合式API而生,要避免其与vue.js 2 中的传统组件选项混合使用,setup函数的返回值可以是俩种类型,如果是返回函数,则该函数作为组件的渲染函数;如果返回数据对象,则将该对象暴露在渲染上下文中。

异步组件

异步组件的实现并不复杂,用户也可以利用promise来自行实现,但是一个完善的异步组件仍然需要考虑很多问题如:

  1. 允许用户指定加载出错时要渲染的组件
  2. 允许用户指定Loading组件,以及展示该组件的延迟时间
  3. 允许用户设置加载组件的超时时长
  4. 组件加载失败时,为用户提供重试的能力

因此vue.js 3 提供了defineAsyncComponent函数,用来自定义异步组件;

内建组件和模块

KeepAlive、Teleport、Transition 组件,共同特点是与渲染器结合紧密,需要框架提供底层的实现与支持;

KeepAlive组件的作用类似于HTTP中的持久连接,可以避免组件不断的被销毁和重建造成的性能开销;实现核心是将组件放入一个隐藏容器中,从而使得可以维持当前状态,当被挂载时,将它从隐藏容器搬到原容器中。

Teleport组件可以完成跨越层级渲染,在很多场景下有用,例如loader,弹出层等;

Transition组件的核心思想是将动效的过程分为多个阶段,在挂载的钩子中动态为其添加样式。

编译器

vue.js 的模板和JSX都属于领域特定语言,它们的实现难度属于中、低级别,只要掌握基本的编译技术理论即可实现功能;

vuejs的模板编译器

工作步骤

  1. 分析模板,将其解析为AST模板
  2. 将模板AST转换为用于描述渲染函数的JavaScript AST
  3. 根据JavaScript AST生成渲染函数代码

AST树构成原理

  1. 用有限状态机构造一个词法分析器,词法分析过程就是状态机在不同状态之间迁移的过程。
  2. 过程中产生一个个TOKEN,形成列表
  3. 扫描Token列表并维护一个开始标签
  4. 每扫到一个开始标签节点,就将其压入栈顶,栈顶节点始终为下一扫码节点的父节点
  5. 扫描完毕形成树形AST

解析器

解析器本质上是一个状态机,正则表达式其实也是一个状态机,因此在编写parser的时候利用正则表达式可以更加效率;

文本模式:解析器在工作时所进入的一些特殊状态,如RCDATA,CDATA,RAWTEXT模式,以及初始DATA模式,不同的模式,解析器对文本解析会有所不同;

递归下降算法:不断递归调用解析子节点函数的过程是递归的含义,下降的含义是随着被递归调用的下降parseChildren函数去构造下级模板AST节点;

编译优化

编译优化是通过编译的手段提取关键信息,并以此指导生成最优代码的过程,关键点在区分 动态节点静态节点;vue3会为动态节点打上标签,在编译时只关注动态节点的更新;

Vue.js 3 在编译优化方面还做了其他努力,具体如下:

  1. 静态提升:能够减少更新时创建虚拟DOM带来的性能开销和内存占用
  2. 预字符串化: 在镜头提升的基础上,对静态节点进行字符串化,可以减少创建虚拟节点产生的性能开销及内存占用;
  3. 缓存内联事件处理函数:避免造成不必要的组件更新
  4. v-once指令 :缓存全部或部分虚拟节点,能够避免组件更新时重新创建虚拟DOM带来的性能开销,也可以避免无用的Diff操作

服务端渲染

vue.js可以实现的渲染方式

  1. 客户端渲染( client-side-rendering, CSR)
  2. 服务端渲染(server-side-rendering, SSR)
  3. 同构渲染(isomorphic rendering)

渲染比对

SSRCSR同构渲染
SEO友好不友好友好
白屏问题
占用服务端资源
用户体验

基于此表可以看出同构渲染是一种高级且优秀的渲染方案,实现流程:

  1. 服务端渲染静态HTML字符串并发送给浏览器
  2. 浏览器渲染静态HTML静态字符串内容
  3. 下载打包在静态资源中的组件代码
  4. 浏览器会解析并执行该组件代码
  5. 浏览器激活DOM
  6. 在虚拟节点与真实DOM元素之间建立联系,即vnode.el = el;这样才能保证后续的程序正确运行
  7. 为DOM元素添加事件绑定

注意事项

  1. 钩子函数不会在服务端执行
  2. 注意跨平台API
  3. 特定端实现,利用cookie信息,在服务端需要从请求头获取,而客户端却是document.cookie
  4. 避免交叉请求引起的状态污染,因为服务器的一对多特性
  5. 仅在客户端渲染组件中的部分内容,自行封装 组件,利用onMounted钩子函数只会在客户端运行的原理;

最后

📚 vue
☃️ 个人简介:一个喜爱技术的人。
🌞 励志格言: 脚踏实地,虚心学习。
❗如果文章还可以,记得用你可爱的小手点赞👍关注✅,我会在第一时间回、回访,欢迎进一步交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/32664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

毕业后河北种水稻 国稻种芯·中国水稻节:安徽姑娘承德务农

毕业后河北种水稻 国稻种芯中国水稻节:安徽姑娘承德务农 (新华每日电讯记者刘金海、方欣、牟宇) 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 中国农民丰收节国际贸易促进会 国稻种芯中国水稻节 中国三农智库网-功能性农业农业大健康大会报道:整…

【Linux】内存查看vmstat命令(虚拟内存统计)

vmstat命令:虚拟内存统计 CPU使用率内存试用虚拟内存交换情况IO读写情况 process r:运行和等待CPU时间片的进程数 超过cpu个数, 出现CPU瓶颈 长时间大于1,CPU不足,需要增加CPU b:正在等待资源的进程数&…

玩转MySQL:定位排查解决突发Bug

引言 前面MySQL优化、调化两文中,聊到了关于数据库性能优化的话题,而本文则再来聊一聊关于MySQL线上排查方面的话题。线上排查、性能优化等内容是面试过程中的“常客”,而对于线上遇到的“疑难杂症”,需要通过理性的思维去分析问…

Java岗位必备技能SpringBoot的面试题集锦

当下SpringBoot框架真的很火,大多数企业把它作为基础技能,考察求职者的能力。如下截图,是我从Boss直聘中找到的,要求SpringBoot是必备技能。 所以非常有必要为了面试,好好归纳下SpringBoot常被提起来的问题。 题目大纲…

Tesseract .Net SDK C# OCR 2022.1

Tesseract .Net SDK C# OCR 库 #将扫描的 PDF 转换为可搜索的文档 #快速准确的基于神经网络的引擎 #纠正低质量扫描 # 120 多种语言 # .Net 2.0, .Net 5, 标准, 核心 Tesseract OCR - industry-fastest .Net OCR library 4 行代码,仅此而已 var api OcrApi.Creat…

[附源码]java毕业设计疫情环境下的酒店管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

不知道什么的复习题

P4408 [NOI2003] 逃学的小孩,一眼就看出要化简题面:不就是找三个点使得ABBC最大嘛,不妨想起直径的性质,最长,而且其他点到它的距离最长。那么直接拿直径来做就行。推导出结论为ansmax(min(dis[A][k],dis[B][k])dis[A][…

CSS3------CSS选择器

界面中的“超文本“本质上就是通过一个一个矩形盒子包起来,然后进行排版组合,那么接下来要详细研究这个标签盒子的细节结构,以帮助学习如何使用它,但是在开始研究它之前,我们先来了解一个概念,选择器的概念…

BN、CBN、CmBN 的对比与总结

BN、CBN、CmBN 的对比与总结 最近看到了关于 Yolo 系列 trick 的总结文章 【Make YOLO Great Again】YOLOv1-v7全系列大解析(Tricks篇),其中提到了 YoloV4 中使用了 CmBN,这是对 CBN 的改进,可以较好的适应小 batch 的…

电容笔值不值得买?电容笔十大品牌排行

要想给我们的ipad配置一款电容笔,如果感觉苹果原装的电容笔价格远远超过预算。这时候平替电容笔是个非常值得入手的选择。试想一下购买一款苹果原装的电容笔的资金都够买整整四款平替电容笔了,平替电容笔价格便宜且功能跟苹果的电容笔相差无几。下面我来…

【设计模式】 - 结构型模式 - 迭代器模式

目录标题前言迭代器模式概述结构实现优缺点JDK源码解析前言 行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象…

ai绘画有哪些软件,盘点三款免费且超级好用的AI绘画工具

Ai绘画有哪些软件?不但可以免费使用,而且生成的画作精美,而且生成的图片速度还要很快? 不用急,今天小编给大家推荐的这三款ai绘画工具完全满足了上述条件! 第一款,重磅级产品,数画…

内存 地址转换、分段、空闲空间管理

目录 1. 地址转换 1.1 动态重定位 1.1.1 基址寄存器(虚拟地址 -> 物理地址) 1.1.2 界限寄存器(提供访问保护) 1.2 操作系统的工作 2. 分段 2.1 分段:泛化的基址/界限 2.2 引用哪个段 2.3 代码和堆的地址转换举例 2.4…

Java#23(常见API--1)

目录 一.Math Math是一个帮助我们用于进行数学计算的工具类 工具类的特点: Math类中的常用方法 二.System System是一个工具类,为我们提供一些与系统相关的办法 一.Math Math是一个帮助我们用于进行数学计算的工具类 工具类的特点: 私有化构造方法,所有的方法都是静态的 M…

[附源码]java毕业设计医院预约挂号管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

web网页设计期末课程大作业 我的美丽家乡盐城 HTML+CSS+JavaScript

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法,如盒子的嵌套、浮动、margin、border、background等属性的使用,外部大盒子设定居中,内部左中右布局,下方横向浮动排列,大学学习的前端知识点和布局方式都有…

Linux C应用编程-2-Makefile编写

1.基本规则 #规则格式 target ... : prerequisites ... command1command2#例如 main: main.o stack.o maze.ogcc main.o stack.o maze.o -o main main是规则的目标(Target),main.o、stack.o和maze.o是规则的条件(Prerequisite&am…

贴地气的安卓UI自动化工具4399AT全面更新了~

4399AT是 一款兼容多设备运行并实现全自动化的测试的安卓UI工具,全自动化测试是指从apk的安装到按钮点击,密码输入到安装完成,不需要人工介入,兼容android5.0-12.0系统大部分品牌,至于开始测试,启动apk后&a…

(十)笔记.net学习Lambda和Linq表达式

1.lambda表达式的演变 Lambda表达式的本质是“匿名方法”: C#的Lambda 表达式都使用 Lambda 运算符 >,该运算符读为“goes to”。语法如下: (object argOne, object argTwo) > {; /*Your statement goes here*/} 函数体多于一条语句…

一次Actuator未授权访问利用

目录 介绍 复现 Actuator目录下可能利用泄漏信息的路径 利用 思考 处理意见 介绍 事先得到同意对朋友公司的网站进行了扫描,扫出了一个Actuator未授权,于是开始复现并记录一下,最后获取了redis的密码 复现 这里是请求包 响应包成功返回…