app开发定制公司vue3 框架学习概念笔记

文章目录

前情提要


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

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

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


框架设计概览

命令式

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

声明式

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

小结

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

性能

操作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钩子函数只会在客户端运行的原理;

最后

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

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发