0
点赞
收藏
分享

微信扫一扫

【L1.第一章】初步认识 Appium 框架结构与优势

君心浅语 2024-08-11 阅读 30

Vue 发展历程

(1)源码优化:

对于 Vue.js 框架本身开发的优化。

目的:让代码更易于开发和维护 

源码的优化主要体现在使用 monorepo和TypeScript 管理和开发源码。

这样做的目标是提升自身代码可维护性 

①更好的代码管理方式: monorepo 

相对于 Vue.js 2.x的源码组织方式,monorepo 把这些模块拆分到不同的 package 中,每个 package 有各自的 API、类型定义和测试

这样使得模块拆分更细化,职责划分更明确,模块之间的依赖关系也更加明确开发人员也更容易阅读、理解和更改所有模块源码,提高代码的可维护性。 

例:package(比如 reactivity 响应式库)是可以独立于 Vue.js 使用的。

这样用户如果只想使用 Vue.js 3.0的响应式能力,可单独依赖这个响应式库。而不用去依赖整个 Vue.js,减小了引用包的体积大小,而 Vue.js2.x是做不到这一点的 

 

②有类型的 JavaScript: TypeScript

——>更有利于代码的维护 

 

  • 因为它可以在编码期间帮你做类型检查  避免一些因类型问题导致的错误
  • 有利于它去定义接口的类型,利于IDE(集成开发环境  常见的IDE有Visual Studio、Eclipse、IntelliJ IDEA等)对变量类型的推导

因此就选用了 TypeScript  进行整个项目的重构,TypeScript 提供了更好的类型检查,能支持复杂类型的推导。源码采用TS编写,也省去了维护地点TS文件的麻烦。

 


(2)性能优化:

对于 Vue.js 2.x 已经足够优秀的前端框架 它的性能优化可以从哪些方面进行突破呢? 

 

①源码体积优化: 

 

 

 

②数据劫持优化: 

Vue.js 区别于 React.js 的一大特色是Vue的数据是响应式的。 

DOM 是数据的一种映射, 数据发生变化后可以自动更新DOM,用户只需要专注于数据的修改,没有其余的性质负担。但是这样子的功能实现必须需要劫持数据的访问与更新

Vue.js 怎么知道更新哪一片 DOM 呢?
因为在渲染 DOM 的时候访问了数据,我们可以对它进行访问劫持

这样就在内部建立了依赖关系,也就知道数据对应的 DOM 是什么了 。内部需要依赖watcher的数据结构做依赖管理

Vue1 和 Vue2  通过 object.defineProperty 进行数据劫持:

劫持了一整个对象,因此对对象属性的增加和删除都能够检测到。 

这样的好处是真正访问到的内部对象才会变成响应式,而不是无脑递归这样无疑也在很大程度上提升了性能。

 


(3)编译优化:Block tree

 响应式过程发生在new Vue到 init 阶段。

代码只有一个动态节点,很多的 diff 和遍历其实是不需要的,导致Windows 性能与模板大小正相关,跟动态节点的数量无关。当一些组件整个模板只有少量动态节点时,这些遍历都是性能的浪费。 

理想状态只需要 diff  这个绑定 message 动态节点的p标签即可 

 


(4)语法API优化: Composition API

①优化逻辑组织 

按照逻辑关注点做颜色编码, 当使用Option API 编写组件时,逻辑关注点都是非常分散的。

开发项目变得复杂时,免不了需要抽象出一些复用逻辑。 

 

 鼠标位置监听的例子:

 如果有大量的Mixin就会有命名冲突和数据来源不清晰。

 


②引入 RFC:

使每个版本改动可控

 

过渡期: 

 


 

组件渲染

 在 Vue.js 中,组件是一个非常重要的概念,整个应用的页面都是通过组件渲染来实现的

 编写组件开始,到最终真实的 DOM 又是怎样的一个转变过程呢?

组件: 

①应用程序初始化:

一个组件可以通过 “模板加对象描述” 的方式创建,组件创建好以后是如何被调用并初始化的呢?

因为整个组件树是由根组件开始渲染的。

为了找到根组件的渲染入口,需要从应用程序的初始化过程开始分析 

  • 在整个 app 对象创建过程中,Vue.js 利用 闭包和函数柯里化 的技巧,很好地实现了参数保留
  • 比如,在执行 app.mount 的时候,不需要传入 渲染器render(因为在执行 createAppAPI的时候渲染器 render 参数已经被保留下来了 )

先思考一下,为什么要重写 app.mount 这个方法而不把相关逻辑放在 app 对象的 mount 方法内部来实现呢? 


 

②核心渲染流程:

创建 vnode 和渲染 vnode 

1️⃣普通元素节点:

 

2️⃣组件节点

即不会真的在页面上渲染一个 CustomComponent 标签,而是渲染组件内部定义的 HTML 标签。

3️⃣纯文本Vnode

4️⃣注释Vnode 

 

内部还针对Vnode tag做了更详细的分类,并且把VNode类型做编码,以便在后面的配置阶段,可以根据不同的类型执行相应的处理逻辑: 

 

那么 vnode 有什么优势呢?
为什么一定要设计 vnode 这样的数据结构呢? 

 

app.mount 内部通过执行 render 函数去渲染创建的 VNode

重点关注对组件的处理、对普通 DOM 元素 两种类型的处理节点的渲染逻辑 

主要操作:创建组件实例, 设置组件实例,设置并运行带副作用的渲染函数

初始渲染主要做两件事情: 渲染组件生成subTree(VNode对象)、把 subTree 挂载到 container 中

  • hello节点渲染生成的Vnode就是hello对应的init Vnode(组件Vnode)
  • hello组件内部的整个DOM节点对应的Vnode就是执行 renderComponentRoot 渲染生成对应的subTree,可以称之为子树Vnode 

每个组件都有对应的render函数 

renderComponentRoot  就是执行 render 函数,创建整个组件内部的Vnode,把这个 Vnode 再经过内部一层标准化就能得到该函数的返回结果即子树Vnode。渲染生成子树Vnode后就是大勇patch函数把子树Vnode挂载到content中。

 

对普通DOM元素的处理流程: 

如果是其他平台比如 Weex,hostCreateElement 方法就不再是操作 DOM而是平台相关的 API了,这些平台相关的方法是在创建渲染器阶段作为参数传入的 

创建完 DOM 节点后,接下来要做的是判断如果有 props 的话给这个 DOM 节点添加相关的 class、style、event等属性,并做相关的处理这些逻辑都是在 hostPatchProp 函数内部做的 

DOM和VNode都是一棵树,并且结构和DOM一一映射。 

处理完所有子节点后, 通过insert的方法把创建DOM元素节点挂载到content下

因为 insert 的执行是在处理子节点后,所以挂载的顺序是先子节点,后父节点
最终挂载到最外层的容器上

在 mountChildren 的时候递归执行的是 patch 函数,而不是 mountElement 函数
这是因为子节点可能有其他类型的vnode,比如组件 vnode

 

  • 梳理了组件渲染的过程,本质上就是把各种类型的 vnode 渲染成真实 DOM
  • 组件是由模板、组件描述对象和数据构成的,数据的变化会影响组件的变化
  • 组件的渲染过程中创建了一个带副作用的渲染函数
  • 当数据变化的时候就会执行这个渲染函数来触发组件的更新 

③ 副作用渲染函数更新组件的过程

举报

相关推荐

0 条评论