百度前端开发二面

1,130 阅读27分钟

接上文,面完百度一面后,百度面试官也是让我通过了一面,迎来了我的百度二面,这不,刚面完就来给大家分享一下百度前端实习开发的二面题目。

一、项目难点

一面问完我一些八股后这不二面上来就问我项目难点,让我介绍一下项目中的难点和亮点,小编我也是赶紧抓住机会展示了一波。框框说了一顿自己的项目。想必各位秋招的小伙伴都有自己的项目也知道怎么介绍吧,这里我就不多说了。

二、大文件如何上传

果然,面试官看到我的项目后就追着我问项目,问我上传过程中遇到大文件如何上传?

大文件上传其实也有很多种方法,我这里和面试官聊的是切片上传。

前端:

1、读取本地的文件,读成一个文件对象

2、使用slice对文件对象进行切割,并得到Blob类型的文件对象

3、将Blob类型的文件对象转成FormData 表单类型的对象

4、发送请求,将FormData对象切片一个一个的发送给后端

核心就是利用 Blob.prototype.slice这个方法,它和数组的slice方法相似,但不是,文件的slice方法可以返回原文件的某个切片,将大文件对象进行切割得到小的Blob对象,由于后端无法识别Blob对象,所以需要转为前后端都能识别的FormData对象,在用post请求发送给后端

预先定义好单个切片大小,将文件切分为一个个切片,然后借助 http 的可并发性,同时上传多个切片。这样从原本传一个大文件,变成了并发传多个小的文件切片,可以大大减少上传时间

另外由于是并发,传输到服务端的顺序可能会发生变化,因此我们还需要给每个切片记录顺序

后端:

1、接受前端传递的切片并解析切片得到数据

2、保存切片到某个文件夹

3、当接受到前端的合并请求后,开始合并切片

4、创建可写流,将所有的切片读成流类型并汇入到可写流中得到完整的文件资源

服务端负责接受前端传输的切片,并在接收到所有切片后合并所有切片

这里又引伸出了两个问题

  1. 何时合并切片,即切片什么时候传输完成
  2. 如何合并切片

第一个问题需要前端配合,前端在每个切片中都携带切片最大数量的信息,当服务端接受到这个数量的切片时自动合并。或者也可以额外发一个请求,主动通知服务端进行切片的合并,我这里采用的是第二种

第二个问题,具体如何合并切片呢?这里我可以使用 Nodejs 的 读写流(readStream/writeStream),将所有切片的流传输到最终文件的流里

具体的实现方法我就不多说了,我之前也写过大文件上传的相关文章,大家可以去看看

大厂面试官:如何实现大文件上传前言 小编我这段时间也是在不断的面试,在面试中也是会遇到许多的问题,这不,要是面试官问你如 - 掘金 (juejin.cn)

大文件上传在面试中也是比较重要的点,还包括一些断电续传啊,都很有可能会被大厂面试官问到的。大家还是要去了解一些的。

三、手写一个控制并发请求

这里面试官也是听到我跟它说完切片上传后临时起兴,又来问我说前端如果有很多切片要传给后端怎么办,或者说前端如果有很多请求要发送给后端怎么办,你能不能手写一个函数来实现一个控制并发的效果。

果然,我就知道面试官很有可能会问道我这个,还好我早有准备。最终也是成功的手写出来了

思路如下:

把这些任务全部装到任务队列里,然后一次性把队列里的前两个取出来运行即可,取到两个后就不在取了,等到某个任务运行结束了之后我们再去递归一下取任务的这个行为,取出任务来去运行

这里我们可以考虑使用队列去请求大量接口。

假定最大并发数是paralleCount=5,我们对接口进行了定义编号,当请求队列池中有一个请求返回后,就向池子中新增一个接口进行请求,依次直到最后一个请求执行完毕。

为了模拟发送起步请求这一操作,这里咱们通过定时器定义一个timeout函数来实现,传入一个时间表示请求耗时。

具体实现我也不细说了,大家可以到我之前写的这篇文章里去看看

前端性能优化——控制并发前言 性能优化这一块在前端是一个比较重要并且常考的知识,小编最近在面试的过程中也是被面试官问到了 - 掘金 (juejin.cn)

四、浏览器如何一次性渲染很多数据呢?

面试官问道我这个的时候我当时心想:嘻嘻,这题我会,这好前几天学啦!

这里其实也是我们前端需要常做的性能优化,因为后端有可能会一次性给我们返回很多数据,甚至十万条,那我们不可能一次性全部渲染到页面上吧。没那么快加载的数据完全可以不用那么快渲染嘛

这里我和面试官说的两种方法是采用时间分片(requestAnimationFrame + fragment)或者采用虚拟列表的方法。

面试官听完我说的也是很认可。嘻嘻。

关于这个浏览器如何一次性渲染很多条数据我单独写了一篇文章来讲,大家可以移步到我的这篇文章中看看

前端如何一次性渲染10万条数据?前言 在面试中这种场景题也经常会被面试官问道,因为这也是前端性能优化的一种,下面小编将给 - 掘金 (juejin.cn)

五、算法题

实现一个斐波那契数列

听完面试官说完问题后,我心想,斐波那契数列?这不是简简单单,右手就行吗?我笑了,于是我框框就是一顿敲代码,马上就搞定跟面试官说写完了

function fib(n) { 
    if (n == 0 || n === 1) return 1; 
    return fib(n - 1) + fib(n - 2);
};

如何优化这个算法

果然,我就知道,不会这么简单,面试官看完后又追问我说如果数字很大这样实现有什么问题?如何优化这个算法?

如果数字很大的话就会进行很多重复的计算,浪费很多不必要的内存和性能,我这里和面试官说的方法是采用闭包加数组缓存的方法

// 闭包 + 数组缓存的形式缓存我们的 fn(X)
let fn = (function () {
  let temp = [0, 1]
  return function (n) {
    let result = temp[n]
    if (typeof result != 'number') {
      result = fn(n - 1) + fn(n - 2)
      temp[n] = result
    }
    return result
  }
})()

利用了闭包和数组缓存的技术来提高效率。

  1. 定义一个立即执行函数表达式(),它返回一个函数。这个 IIFE 创建了一个私有作用域,在其中定义了一个数组 temp,用于缓存已计算过的斐波那契数列值。
  2. 返回的函数会检查传入的参数 n 是否已经在 temp 数组中有对应的值。如果有,则直接返回该值;如果没有,它将递归地调用自身来计算 n-1n-2 的值,并将这两个值相加得到 n 的值。
  3. 在递归调用返回之前,将计算出来的值存储到 temp 数组的相应位置,以备后续使用。
  4. 最后返回计算结果。

或者可以采用动态规划的方法优化

时间复杂度是O(n^2),而且递归(自顶向下)的过程中有很多重复计算,我们可以缓存,当然这里可以一步到位,用动态规划(自下向上,状态转移方程),将时间复杂度降到O(n),代码又有了。

function fibonacci(n) {
    if (n <= 1) return n; 
    let fib = [0, 1]; // 保存斐波那契数列的结果 
    for (let i = 2; i <= n; i++) { 
        fib[i] = fib[i - 1] + fib[i - 2]; // 计算第i个斐波那契数 
    } 
    return fib[n]; 
}

六、position有哪些属性

position属性概述

position 属性用于指定一个元素在文档中的定位方式。主要有五种属性值:staticrelativeabsolutefixedsticky

1. static
  • 默认值:所有元素的默认定位方式。
  • 特性:元素按照正常的文档流排列,不受 toprightbottomleft 等定位属性影响。
2. relative
  • 特性:元素仍然处于正常文档流中,但可以使用 toprightbottomleft 属性进行偏移,偏移相对于其正常位置。
3. absolute
  • 特性:元素脱离文档流,相对于最近的已定位(relativeabsolutefixed)的祖先元素进行定位。如果没有已定位的祖先元素,则相对于初始包含块(通常是文档的根元素)进行定位。
4. fixed
  • 特性:元素脱离文档流,相对于浏览器窗口进行定位,无论页面滚动如何变化,元素始终保持在指定位置。
5. sticky
  • 特性:元素在正常文档流中,基于用户的滚动位置进行定位。在超过指定的阈值(通过 toprightbottomleft 属性设置)之前表现为相对定位,超过阈值后表现为固定定位。

使用场景总结

1、static:默认值,一般不需要特别指定,除非需要覆盖其他指定的 position 值。 2、relative:在需要对元素进行轻微调整且保持其在文档流中的位置时使用。 3、absolute:在需要将元素精确定位并从文档流中移除时使用,如弹出框、悬浮菜单等。 4、fixed:在需要元素固定在视口特定位置时使用,如固定导航栏、侧边栏等。 5、sticky:在需要元素在滚动时固定但仍受文档流影响时使用,如滚动表头。

七、absolute是怎么定位的?

1.相对定位:相对于块级元素(或行内块)自身位置进行定位;

2.绝对定位:绝对定位的盒子是相对于离它最近的一个已定位的盒子进行定位的(默认是body);

绝对定位元素相对的元素是它最近的一个祖先,该祖先满足:position的值必须是:relative、absolute、fixed,若没有这样的祖先则相对于body进行定位

​ 注意:css描述的绝对定位概念,没有说明是离他最近的一个已相对定位的盒子进行定位的,所以离他最近的盒子的定位可以是相对定位(relative)和绝对定位(absolute)的,但是在开发中,一般是父盒子设置相对定位的,但是不代表只能是相对定位。

八、css有哪些单位

常见的就是px、em、rem、vw、vh

1、px:相对长度单位。像素px是相对于显示器屏幕分辨率而言的。

2、em:相对长度单位。基准点为父节点字体的大小,即相对于当前对象内文本的字体尺寸(继承父节点字体大小)。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸( 16px )。

3、rem:相对长度单位。r’是“root”的缩写,相对于根元素的字体大小。

4、vh and vw:相对于视口的高度和宽度,而不是父元素的(CSS百分比是相对于包含它的最近的父元素的高度和宽度)。

5、vmin and vmax:关于视口高度和宽度两者的最小值或者最大值。

6、pt 设备像素(物理像素)

7、dpr = 设备像素 / 设备独立像素

8、ppi 每英寸像素,值越大,图像越清晰

九、浏览器的强缓存和协商缓存

一、缓存介绍 1、什么是缓存? 缓存是一种保存资源副本并在下次请求时直接使用该副本的技术。

2、为什么需要缓存? 如果没有缓存的话,每次网络请求都要加载大量的图片和资源,这会使页面的加载变慢许多。 缓存的目的就是为了尽量减少网络请求的体积和数量,让页面加载的更快,节省带宽,提高访问速度,降低服务器压力。

3、哪些资源可以被缓存?——静态资源(css、js、img) 网站的 html 是不能被缓存的。因为网站在使用过程中 html 随时有可能被更新,随时有可能被替换模板。 网页的业务数据也是不能被缓存的。比如留言板和评论区,用户随时都可以在底下评论,那数据库的内容就会被频繁被更新。

二、强制缓存 1、定义: 强缓存:浏览器不会向服务器发送任何请求,直接从本地缓存中读取文件并返回。

三、协商缓存

1、定义

协商缓存是一种服务端缓存策略,即通过服务端来判断某件事情是不是可以被缓存。 服务端判断客户端的资源,是否和服务端资源一样,如果一致则返回304,反之返回200和最新的资源。

十、协商缓存如何设置

设置协商缓存的方式有两种(Last-Modified , If-Modified-Since) & (ETag , If-None-Match)

1) Last-Modified , If-Modified-Since

Last-Modified 资源最后修改的时间,对应请求头为 If-Modified-Since,Last-Modified 只能精确到秒级

image-20240917154540901

当浏览器第一次发请求时,服务器返回资源并在返回头中返回一个Last-Modified 的值给浏览器。这个Last-Modified 的值给到浏览器之后,浏览器会通过 If-Modified-Since 的字段来保存 Last-Modified 的值,且 If-Modified-Since 保存在请求头当中。 之后浏览器再次发送请求时,请求头会带着 If-Modified-Since 的值去找服务器,服务器此时就会匹配浏览器发过来的 If-Modified-Since 是否和自己最后一次修改的 Last-Modified的值相等。如果相等,则返回304,表示资源未被修改;如果不相等,则返回200,并返回资源和新的 Last-Modified的值。

2)Etag,If-None-Match

Etag 资源唯一标识,所谓唯一,可以想象是每个人的身份证,具有唯一性;Etag本质是一个字符串;对应请求头为 If-None-Match

image-20240917154642930

当浏览器第一次发送请求时,服务器返回资源并返回一个 Etag 的值给浏览器。这个 Etag 的值给到浏览器之后,浏览器会通过 If-None-Match 的字段来保存 Etag 的值,且 If-None-Match 保存在请求头当中。 之后当浏览器再次发送请求时,请求头会带着 If-None-Match 的值去找服务器,服务器此刻就会匹配浏览器发过来的 If-None-Match 是否和自己最后一次修改的 Etag 的值相等。如果相等,则返回 304 ,表示资源未被修改;如果不相等,则返回 200 ,并返回资源和新的 Etag 的值。 3、对比 1、当响应头部 Response Headers 同时存在 Last-Modified 和 Etag 的值时,会优先使用Etag; Etag优先级是高于Last-Modifed的,所以服务器会优先验证Etag 2、Last-Modified 只能精确到秒级,而Etag可以更精确。 Etag可以更精确 3、如果资源被重复生成,而内容不变,则Etag更精确

十一、https的攻击

浏览器的安全和攻击问题大家还是也需要去了解了解的,面试中也会被问道,像小编我当时这题可能答的就不是很好。

HTTPS(超文本传输安全协议)是用于加密网站通信的安全协议,它在 HTTP 协议的基础上加入了 TLS/SSL 加密层。尽管 HTTPS 提供了加密保护,但仍然存在多种类型的攻击和威胁。

HTTPS 攻击类型

  1. 中间人攻击(Man-in-the-Middle Attack, MITM)
    • 攻击者位于发送方和接收方之间,篡改或窃听他们的通信。
    • 防护措施:确保使用正确的证书颁发机构(CA)签名的证书,并定期检查证书的有效性和真实性。使用最新的 TLS 版本,禁用弱加密算法。
  2. SSL 剥离(SSL Stripping)
    • 攻击者将 HTTPS 请求降级为 HTTP 请求,绕过加密保护。
    • 防护措施:强制 HTTPS 连接,例如使用 HSTS(HTTP Strict Transport Security)头字段来强制浏览器始终使用 HTTPS。
  3. 证书欺骗(Certificate Impersonation)
    • 攻击者伪造合法站点的证书来欺骗用户。
    • 防护措施:定期检查证书的有效性,并使用证书透明度(Certificate Transparency, CT)来检测伪造证书。
  4. TLS/SSL 漏洞攻击
    • 利用 TLS/SSL 协议中的已知漏洞进行攻击,如 POODLE、BEAST、DROWN 等。
    • 防护措施:及时更新 TLS/SSL 库,禁用已知存在漏洞的协议版本和加密套件。
  5. DDoS 攻击(分布式拒绝服务攻击)
    • 攻击者使用大量流量或请求淹没服务器,使其无法正常响应合法用户的请求。
    • 防护措施:使用防火墙、负载均衡器和 CDN 服务来分散流量,并实施流量清洗服务。
  6. 服务器配置错误
    • 不正确的服务器配置可能会暴露敏感信息或导致安全漏洞。
    • 防护措施:定期进行安全审计,确保服务器配置正确无误,关闭不必要的服务和端口。
  7. 弱密钥交换(Weak Key Exchange)
    • 攻击者利用弱密钥交换算法进行中间人攻击。
    • 防护措施:使用强密钥交换算法,如 ECDHE(椭圆曲线 Diffie-Hellman 密钥交换)。
  8. 侧信道攻击(Side-channel Attacks)
    • 攻击者通过分析网络流量模式或时间来推测加密信息。
    • 防护措施:使用加密算法和协议,确保加密强度足够高,并尽量减少信息泄露。
  9. 会话劫持(Session Hijacking)
    • 攻击者窃取用户的会话信息,如会话 ID 或 Cookie,以冒充合法用户。
    • 防护措施:使用安全的会话管理机制,如 HTTPOnly 标志和 Secure 标志来保护 Cookie,定期刷新会话。

如何保护 HTTPS

为了保护 HTTPS,可以采取以下措施:

  1. 使用最新的加密标准:确保使用最新的 TLS 版本,并禁用 SSLv3 及之前的旧版协议。
  2. 定期更新和补丁:及时更新服务器软件和库,修复已知的安全漏洞。
  3. 启用 HSTS:使用 HSTS 强制浏览器始终使用 HTTPS。
  4. 监控和日志记录:记录访问日志,监控异常活动,并及时响应安全事件。
  5. 使用 CDN 和负载均衡器:分发流量,减轻服务器负担,并提高可用性。
  6. 实施严格的访问控制:确保只有授权用户可以访问敏感资源。
  7. 定期进行安全审计:定期评估系统的安全状况,并修复发现的问题。

十二、vue3和vue2的区别

一. 根节点不同

  • vue2中必须要有根标签

  • vue3中可以没有根标签,会默认将多个根标签包裹在一个fragement虚拟标签中,有利于减少内存。

二. 组合式API和选项式API

  • 在vue2中采用选项式API,将数据和函数集中起来处理,将功能点切割了当逻辑复杂的时候不利于代码阅读。
  • 在vue3中采用组合式API,将同一个功能的代码集中起来处理,使得代码更加有序,有利于代码的书写和维护。

三、响应式原理不同

  • vue2通过Object.definedProperty()的get()和set()来做数据劫持、结合和发布订阅者模式来实现,Object.definedProperty()会遍历每一个属性。

  • vue3通过proxy代理的方式实现。

  • proxy的优势:不需要像Object.definedProperty()的那样遍历每一个属性,有一定的性能提升proxy可以理解为在目标对象之前架设一层“拦截”,外界对该对象的访问都必须通过这一层拦截。这个拦截可以对外界的访问进行过滤和改写。

  • 当属性过多的时候利用Object.definedProperty()要通过遍历的方式监听每一个属性。利用proxy则不需要遍历,会自动监听所有属性,有利于性能的提升

四、生命周期

​ 大部分生命周期在vue2的周期前加 on 即可;vue3没有beforeCreate 和 created两个周期,那想在这两个周期中进行逻辑处理怎么办呢? setup中写好了调用即可

五、vue3不推荐使用mixin进行复用逻辑提取,而是推荐写成hook

六、v-model应用于组件时,监听的事件和传递的值改变

七、ts更好地配合

八、一些细节的改变

1,因为改成组合式api所以没有this

2,生命周期没有creat,setup等同于create,卸载改成unmount

3,vue3中v-if高于v-for的优先级

4,根实例的创建从new app变成了createApp方法

5,一些全局注册,比如mixin,注册全局组件,use改成了用app实例调用,而不是vue类调用

6,新增了传送门teleport组件

7,template模板可以不包在一个根div里

速度更快 体积减少 更易维护 更接近原生 更易使用

1.速度更快

Vue3相比Vue2

重写了虚拟Dom实现 编译模板的优化 更高效的组件初始化 undate性能提高1.32倍 SSR速度提高了23倍

2.体积更小

通过webpack的tree-shaking功能,可以将无用模块“剪辑”,仅打包需要的

能够tree-shaking,有两大好处:

对开发人员,能够对vue实现更多其他的功能,而不必担忧整体体积过大 对使用者,打包出来的包体积变小了 vue可以开发出更多其他的功能,而不必担忧vue打包出来的整体体积过多

3.更易维护

compositon Api 可与现有的Options API一起使用 灵活的逻辑组合与复用 Vue3模块可以和其他框架搭配使用

更好的Typescript支持 Vue3是基于typescipt编写的,可以享受到自动的类型定义提示

编译器重写

4.更接近原生

可以自定义渲染 API

5.更易使用

响应式 API 暴露出来

轻松识别组件重新渲染原因

十三、vue3中v-if相比v-for的优先级体现在哪里

在 Vue 3 中,v-if 指令的优先级高于 v-for。这意味着当两者同时出现在同一个元素上时,Vue 会首先处理 v-if,然后再处理 v-for。这是因为 Vue 3 对 v-ifv-for 的优先级进行了调整,与 Vue 2 的行为不同。

当它们同时存在于一个节点上时,v-ifv-for 的优先级更高。这意味着 v-if 的条件将无法访问到 v-for 作用域内定义的变量别名。

优先级体现的地方

  1. 条件渲染前的循环
    • 在 Vue 3 中,如果同时使用 v-ifv-for,Vue 会首先根据 v-if 的条件来决定是否渲染元素,如果 v-if 的条件为 false,则不会执行 v-for 指令,即使 v-for 指令存在也不会执行循环渲染。
    • 这种顺序可以影响渲染性能,因为在某些情况下,如果 v-if 的条件始终为 false,则可以完全避免 v-for 的执行。
  2. 元素的创建和销毁
    • v-if 的条件为 false 时,与之关联的元素将不会被创建或渲染,即使 v-for 指令存在。
    • 这意味着如果一个元素上有 v-ifv-for,并且 v-if 的条件经常变化,那么每次 v-if 的条件变为 true 时,都需要重新创建和销毁元素及其子元素。

十四、v-if中的key

key 是什么

简单来说key是给每一个vnode的唯一id,同时也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点

1.vue中使用for循环的话要加上:key 他的值是唯一的标识,这个唯一标识最好是item的id。因为vue组件高度复用的原因,增加key可以标识组件的唯一性,也是为了更好的区分个别组件

2.key主要的作用是高效更新虚拟DOM和diff算法用的,diff算法是同级进行比较,比较当前标签上的key和标签名,如果key和标签名都一样时只做一个移动的操作,不会重新创建元素和删除元素。

3.在我们for循环时,没有key的话,会默认使用“就地复用”策略。这时如果数据的顺序被改变,vue不是移动DOM元素来匹配数据的改变,而是复用原来位置的元素。比如这时删除第一个元素,在进行比较时发现标签一样但值不一样,就会复用之前的位置,将新值直接放到该位置,以此类推,最后多出一个时就会把最后一个删掉。

4.要注意的是,在对key进行赋值时,最好不要使用索引值index作为key值。因为如果我们使用index为key值,这时在数组中指定位置插入一个新元素,就会重新更新index,以及后边对应虚拟DOM的key也会更新。因此在项目中index虽然能够解决key不冲突的问题,但是并不能解决复用的情况。如果是静态数据的话 ,使用索引index做key值是没有问题的。

为什么要key

1、vue中列表循环需要加:key='唯一标识',唯一标识尽量是id,目的是为了高效地更新虚拟DOM 2、key主要用于dom diff算法,diff算法为同级比较,比较当前标签上的key还有他当前的标签名,如果key和标签名都一样时只移动,不会重新创建元素和删除元素 3、没有key地时候默认使用就地复用策略。如果数据的顺序被改变,vue不是移动DOM元素来匹配数据项的改变,而是简单复用原来位置的每个元素,在进行比较时发现标签一样值不一样时,就会复用之前的位置,将新值直接放到该位置,以此类推,最后多出一个就会把最后一个删除掉。 4、尽量不要使用索引值index作key值,一定要用唯一标识的值,如id等。因为若用数组索引index为key,当向数组中指定位置插入一个新元素后,因为这时候会重新更新index索引,对应着后面的虚拟DOM的key值全部更新了,这个时候还是会做不必要的更新,就像没有加key一样,因此index虽然能够解决key不冲突的问题,但是并不能解决复用的情况。如果是静态数据,用索引号index做key值是没有问题的。

十五、diff算法

聊到v-for里面的key,自然也就不可避免的跟面试官聊聊vue的diff算法了。

聊diff算法之前咱们要先来了解一下虚拟dom这个东西

虚拟dom的定义与作用

什么是虚拟dom

大家一定要记住的一点就是,虚拟dom就是一个普通的js对象。是一个用来描述真实dom结构的js对象,因为他不是真实dom,所以才叫虚拟dom。

虚拟dom的结构

从下图中,我们来看一看虚拟dom结构到底是怎样的

image-20240917162235293

虚拟dom的作用

1、我们都知道,传统dom数据发送变化的时候,我们都需要不断的去操作dom,才能更新dom的数据,虽然后面出现了模板引擎这种东西,可以让我们一次性去更新多个dom。但模板引擎依旧没有一种可以追踪状态的机制,当引擎内某个数据发生变化时,他依然要操作dom去重新渲染整个引擎。 而虚拟dom可以很好的跟踪当前dom状态,因为他会根据当前数据生成一个描述当前dom结构的虚拟dom,然后数据发送变化时,又会生成一个新的虚拟dom,而这两个虚拟dom恰恰保存了变化前后的状态。然后通过diff算法,计算出两个前后两个虚拟dom之间的差异,得出一个更新的最优方法(哪些发生改变,就更新哪些)。可以很明显的提升渲染效率以及用户体验 2、因为虚拟dom是一个普通的javascript对象,故他不单单只能允许在浏览器端,渲染出来的虚拟dom可同时在node环境下或者weex的app环境下允许。有很好的跨端性

什么是diff算法

diff算法就是用于比较新旧两个虚拟dom之间差异的一种算法。

diff全称就是different,就是找不同,找新老虚拟dom的不同,找到并产生一个补丁包

diff算法代码我们不用管,只需要知道原理即可

  1. 同层比较,是不是相同的节点,不相同直接废弃OldVDom
  2. 是相同节点,比较节点上的属性,产生一个补丁包path
  3. 继续比较子节点下一层的子节点,采用双端队列的方式,尽量复用,产生一个补丁包
  4. 同上

至于具体的diff算法想要深入了解的小伙伴这里我给大家推荐一篇写的比较好的文章。大家可以去看看

vue 虚拟dom和diff算法详解_vue的dom diff算法-CSDN博客

总结

经过历时将近一个半小时的拷打,小编我也是终于挺了过来,和面试官口舌大战一个半小时,大部分问题也都基本回答上来了,面试官对我的表现总体也还算满意,过来一两天也是给我打电话告诉我通过了这次的百度二面,约我进行下一轮百度的三面。哎,大厂的面试真难啊,加油吧!努力的少年!