前端面试题 查缺补漏ing

374 阅读8分钟

webpack相关

一、webpack的打包原理

识别入口文件 通过逐层识别模块依赖(Commonjs、amd或者es6的import,webpack都会对其进行分析,来获取代码的依赖) webpack做的就是分析代码,转换代码,编译代码,输出代码 最终形成打包后的代码

二、什么是loader

loader是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中

处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行

第一个执行的loader接收源文件内容作为参数,其它loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的JavaScript源码

三、什么是plugin

在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。

四、loader和plugin的区别

对于loader,它是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss转换为A.css,单纯的文件转换过程

plugin是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务

vue相关

vue2和vue3的区别

1、生命周期的改变

(1)vue2中的beforeCreate和created被一个新增的setup生命周期函数代替,setup函数会在组件创建之前就执行。

(2)beforeDestory和destoryed分别改名为beforeUnmount和unmounted。

2、性能方面的改变

(1)数据劫持方面的改变,由原来的Object.defineProperty()进行数据劫持,改变为Proxy进行数据代理。由于proxy可以动态判断该数据是否为深层嵌套数据,而object.defineProperty()为遍历深层嵌套数据,导致了两者在数据劫持上产生了时间上的巨大差距。

(2)打包策略,vue3支持了tree-shaking,排除任何未实际使用的代码,打包体积减小。由于打包后体积减小,页面加载文件所需的时间也极大缩短。

(3)diff优化,vue3中会对静态节点进行提升,所有的静态节点在进行对比时不会被遍历。在进行节点对比时所需的时间也大大减少。

3、新增的compositionAPI(组合式API)

解决了Vue2.X版本的optionsAPI不能解决的复用和可读性差的缺陷。

新增了一个setup()生命周期函数,会在组件创建之前就执行。用setup生命周期代替beforeCreate和created。

const {ref,reactive,onMountend,toRefs} = Vue
setup(props){
  // 声明简单数据类型和复杂数据类型
  // 只能通过.value的形式获取数据
  const refValue = ref(null);
  // 只能声明复杂数据类型
  // 声明的数据类型不能解构
  // 声明的数据类型是proxy对象
  const reactiveValue = reactive({state:0});
  // 生命周期的使用(on加生命周期名字)
  onMountend(()=>{
     // 在相应的生命周期内执行相应操作
  })
  // 该类型的数据不能解构,解构就会失去响应式特点
  console.log(props);
  // 该方法将proxy对象转化成ref变量
  toRefs(props);
} 

4、v-model的变化

支持绑定多个v-model进行双向绑定。

介绍下重绘和回流,以及如何优化

1. 浏览器渲染机制

浏览器采用流式布局模型(Flow Based Layout)

浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tree)。

有了RenderTree,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。

由于浏览器使用流式布局,对Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用table布局的原因之一。

2. 重绘

由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,称为重绘,例如outline, visibility, color、background-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。

3. 回流

回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或是整个页面)的布局更新。一个元素的回流可能会导致了其所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流。

<body>
<div class="error">
    <h4>我的组件</h4>
    <p><strong>错误:</strong>错误的描述…</p>
    <h5>错误纠正</h5>
    <ol>
        <li>第一步</li>
        <li>第二步</li>
    </ol>
</div>
</body>

在上面的HTML片段中,对该段落(<p>标签)回流将会引发强烈的回流,因为它是一个子节点。这也导致了祖先的回流(div.error和body – 视浏览器而定)。此外,<h5><ol>也会有简单的回流,因为其在DOM中在回流元素之后。大部分的回流将导致页面的重新渲染。

回流必定会发生重绘,重绘不一定会引发回流。

4. 浏览器优化

现代浏览器大多都是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少一个浏览器刷新(即16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能有会影响这些属性或方法返回值的操作,即使没有,浏览器也会强制清空队列,触发回流与重绘来确保返回正确的值。

主要包括以下属性或方法:

offsetTop、offsetLeft、offsetWidth、offsetHeight scrollTop、scrollLeft、scrollWidth、scrollHeight clientTop、clientLeft、clientWidth、clientHeight width、height getComputedStyle() getBoundingClientRect() 所以,我们应该避免频繁的使用上述的属性,他们都会强制渲染刷新队列。

5. 减少重绘与回流

CSS

  • 使用 transform 替代 top

  • 使用 visibility 替换 display: none ,因为前者只会引起重绘,后者会引发回流(改变了布局

  • 避免使用table布局,可能很小的一个小改动会造成整个 table 的重新布局。

  • 尽可能在DOM树的最末端改变class,回流是不可避免的,但可以减少其影响。尽可能在DOM树的最末端改变class,可以限制了回流的范围,使其影响尽可能少的节点。

  • 避免设置多层内联样式,CSS 选择符从右往左匹配查找,避免节点层级过多。

<div>
  <a> <span></span> </a>
</div>
<style>
  span {
    color: red;
  }
  div > a > span {
    color: red;
  }
</style>

对于第一种设置样式的方式来说,浏览器只需要找到页面中所有的 span 标签然后设置颜色,但是对于第二种设置样式的方式来说,浏览器首先需要找到所有的 span 标签,然后找到 span 标签上的 a 标签,最后再去找到 div 标签,然后给符合这种条件的 span 标签设置颜色,这样的递归过程就很复杂。所以我们应该尽可能的避免写过于具体的 CSS 选择器,然后对于 HTML 来说也尽量少的添加无意义标签,保证层级扁平。

  • 将动画效果应用到position属性为absolute或fixed的元素上,避免影响其他元素的布局,这样只是一个重绘,而不是回流,同时,控制动画速度可以选择 requestAnimationFrame,详见探讨 requestAnimationFrame。

  • 避免使用CSS表达式,可能会引发回流。

  • 将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点,例如will-change、video、iframe等标签,浏览器会自动将该节点变为图层。

  • CSS3 硬件加速(GPU加速),使用css3硬件加速,可以让transform、opacity、filters这些动画不会引起回流重绘 。但是对于动画的其它属性,比如background-color这些,还是会引起回流重绘的,不过它还是可以提升这些动画的性能。

JavaScript

  • 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
  • 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
  • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
  • 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。