关于前端:教你阅读vue源码的正确姿势看完就学废

49次阅读

共计 2461 个字符,预计需要花费 7 分钟才能阅读完成。

简介一下集体浏览 vue 源码的姿态,有倡议欢送评论区补充哈~

一、源码浏览姿态

1. 先整体 – 后细节

  • 先弄清楚源码分为哪几个模块,整套流程是怎么将各个模块串起来的。
  • 而后细化理解每个模块的外围原理。

2. 站在他人的肩膀上

  • 不必一股脑扎进源码仓库里一点点啃,这样很低效,实用于对源码较为理解的人
  • 举荐先读他人的源码简介,源码剖析,弄清楚脉络,还有每个局部的大略性能和外围流程。心里带着思路去看源码实现。
  • 少数状况不须要逐行代码的细究,但针对某些外围性能的实现须要细究,例如:虚构 dom、diff 算法、数据驱动、响应式实现以及组件化等外围的性能的外围实现举荐细看。

3. 读多遍

  • 一次粗读 :看整体流程,看每个模块的外围性能和职责,领会平时写的代码在源码外面通过了什么步骤体现到了页面上。
  • 二次精读 :看细节实现,弄清楚外围模块的实现形式(如弄懂 diff 算法思路,最好本人入手实现)。
  • 三次领悟 :领悟源码整体架构和设计思维,领会每个模块之间如何配合合作,架构如何组织。

二、步骤

  • 依赖剖析组装:路由、父子组件层级
  • 模版编译:解析成 AST 语法树,进而构建虚构 dom 树
  • 装载页面:虚构 dom 整体转化为实在 dom
  • 部分更新:响应式数据监控到变动,diff 比拟数据变动前后的虚构 dom 树差别,部分更新 dom
  • 销毁:销毁虚构 dom,移除 dom

三、vue 源码导读

  • template 格调、对象配置格调
  • 虚构 dom 思维(js 对象操作代替 dom 操作)
  • diff 算法思维(同层比拟,增加、挪动、删除)
  • 组件化思维(组件编译、组件通信)
  • 数据响应式(依赖收集、派发更新,公布订阅)

四、vue3 新个性理解

vue2.x 的痛点:

  • 源码本身的维护性;
  • 数据量大后带来的渲染和更新的性能问题;
  • 一些想舍弃但为了兼容始终保留的鸡肋 API 等;
  • TypeScript 反对;

vue3.0 优化点:

  • 一、应用 monorepo 治理源码
  • 二、应用 TypeScript 开发源码
  • 三、性能优化 1. 源码体积优化 2. 数据劫持优化 Proxy 3. 编译优化 4.diff 算法优化
  • 四、语法 API 优化:Composition API

插一个题外话,小编整顿了下用 Vue 3.0 来写个小程序框架的 PDF 材料,感兴趣的小伙伴们请点击这里支付

五、细究一下 diff 算法

vue2 的 diff

组件更新外围是响应式数据监控到数据的扭转,从新生成了虚构 dom 树,而后通过 diff 算法计算出前后虚构 dom 树的差别点,更新 dom 时只更新变动的局部。快问快答:

1. 为什么要 diff?

答:O(n^3) 意味着如果要展现 1000 个节点,就要顺次执行上十亿次的比拟,无奈接受大数据量的比照。

间接比拟和批改两个树的复杂度为什么是 n^3?

答:老树的每一个节点都去遍历新树的节点,直到找到新树对应的节点。那么这个流程就是 O(n^2),再紧接着找到不同之后,再计算最短批改间隔而后批改节点,这里是 O(n^3)。

2. diff 的策略是什么?有什么依据?

答:1、Web UI 中 DOM 节点跨层级的挪动操作特地少,能够忽略不计,因而仅进行同层比拟。2、如果父节点不同,放弃对子节点的比拟,间接删除旧节点而后增加新的节点从新渲染;3、如果子节点有变动,Virtual DOM 不会计算变动的是什么,而是从新渲染。4、同级多个节点可通过惟一的 key 比照异同;

3. diff 流程是什么?

答:新旧节点不同:创立新节点 ➜ 更新父占位符节点 ➜ 删除旧节点;新旧节点雷同且没有子节点:不变;新旧节点雷同且都有子节点:遍历子节点同级比拟,做挪动、增加、删除三个操作,具体见下图;

vue3.0 的 diff

深度递归遍历 vnode 树,节点的标签和 key 雷同认为是同一个节点则更新,不同则删除,而后解决子节点。子节点分这几种状况解决:纯文本、vnode 数组和空

空往往意味着增加或删除;纯文本雷同间接更新 innerText,不同则删除;新旧子节点都是 vnode 数组则 diff 算法来解决;

vue3.0 diff 算法思维

  • 编译模版时进行动态剖析,标记动静节点,diff 比照差别时仅比照动静节点(性能晋升显著);
  • diff 算法先去头去尾,借此缩短遍历比照数组长度(对数组插入和删除操作性能优化显著);
  • 通过对更新前后子节点数组建设映射表的形式,将 O(n^2) 复杂度的遍历升高到 O(n);
  • 通过最长递增子序列办法了来 diff 前后的子节点数组,缩小挪动操作的次数;

最长递增子序列算法实现

/*
 * 寻找最长递增子序列
 * 应用动静布局思维,a -> c = a -> b + b -> c
 * 其中 p 数组存储的是从 p[p[i]] 到 p[i] 的最长递增子序列索引,也就是前一个 b 的索引;* r 数组存储最初一个元素也就是 c 的索引
 */
 function getSequenceOfLIS(arr) {const p = [0];
    const result = [0];
    for (let i = 0; i < arr.length; i ++) {const val = arr[i];
        const top = result[result.length - 1];
        if (arr[top] < val) {p[i] = top;
            result.push(i);
            continue;
        }
        // 二分法搜寻
        let l = 0, r = result.length - 1;
        while(l < r) {const c = (l + r) >> 1;
            if (arr[result] < val) {l = c + 1;} else {r = c;}
        }
        if (val < arr[result[l]]) {if (l > 0) {p[i] = result[l - 1]
            }
            result[l] = i;
        }
    }
    // 回朔 p 数组,找出最长递增子序列
    let preIndex = result[result.length - 1];
    for (let i = result.length - 1; i > 0; i --) {result[i] = preIndex;
        preIndex = p[preIndex]
    }
    return result;
}

浏览 vue 源码姿态小伙伴们你们学废了嘛,你们都是如何浏览的呢,欢送评论留言通知小编哦。

还有想学用 Vue 3.0 来写个小程序框架的小伙伴们记得支付!点击这里也是一样能够支付的

求点赞求反对!提前祝小伙伴们五一高兴嗷!

正文完
 0