front-end-interview-preparation
前端面试准备
计算机网络
-
了解http吗?
HTTP 是一个基于 TCP/IP 通信协议来传递数据(HTML 文件、图片文件、查询结果等),工作于客户端-服务端架构上。
HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包,HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换资料的隐私与完整性。 -
TCP 三次握手和四次握手的过程
三次握手第一次握手,客户端向服务器发送一个 SYN 连接请求报文段,报文段的首部中 SYN 标志位置为 1,序号字段是一个任选的随机数。它代表的是客户端数据的初始序号。
第二次握手,服务器端接收到客户端发送的 SYN 连接请求报文段后,服务器首先会为该连接分配 TCP 缓存和变量,然后向客户端发送 SYN ACK 报文段,报文段的首部中 SYN 和 ACK 标志位都被置为 1,代表这是一个对 SYN 连接请求的确认,同时序号字段是服务器端产生的一个任选的随机数,它代表的是服务器端数据的初始序号。确认号字段为客户端发送的序号加一。
第三次握手,客户端接收到服务器的肯定应答后,它也会为这次 TCP 连接分配缓存和变量,同时向服务器端发送一个对服务器端的报文段的确认。第三次握手可以在报文段中携带数据。
在我看来,TCP 三次握手的建立连接的过程就是相互确认初始序号的过程,告诉对方,什么样序号的报文段能够被正确接收。
第三次握手的作用是客户端对服务器端的初始序号的确认。如果只使用两次握手,那么服务器就没有办法知道自己的序号是否已被确认。同时这样也是为了防止失效的请求报文段被服务器接收,而出现错误的情况。
四次握手因为 TCP 连接是全双工的,也就是说通信的双方都可以向对方发送和接收消息,所以断开连接需要双方的确认。
第一次挥手,客户端认为没有数据要再发送给服务器端,它就向服务器发送一个 FIN 报文段,申请断开客户端到服务器端的连接。发送后客户端进入 FIN_WAIT_1 状态。
第二次挥手,服务器端接收到客户端释放连接的请求后,向客户端发送一个确认报文段,表示已经接收到了客户端释放连接的请求,以后不再接收客户端发送过来的数据。但是因为连接是全双工的,所以此时,服务器端还可以向客户端发送数据。服务器端进入 CLOSE_WAIT 状态。客户端收到确认后,进入 FIN_WAIT_2 状态。
第三次挥手,服务器端发送完所有数据后,向客户端发送 FIN 报文段,申请断开服务器端到客户端的连接。发送后进入 LAST_ACK 状态。
第四次挥手,客户端接收到 FIN 请求后,向服务器端发送一个确认应答,并进入 TIME_WAIT 阶段。该阶段会持续一段时间,这个时间为报文段在网络中的最大生存时间,如果该时间内服务端没有重发请求的话,客户端进入 CLOSED 的状态。如果收到服务器的重发请求就重新发送确认报文段。服务器端收到客户端的确认报文段后就进入 CLOSED 状态,这样全双工的连接就被释放了。
TCP 使用四次挥手的原因是因为 TCP 的连接是全双工的,所以需要双方分别释放到对方的连接,单独一方的连接释放,只代表不能再向对方发送数据,连接处于的是半释放的状态。
最后一次挥手中,客户端会等待一段时间再关闭的原因,是为了防止发送给服务器的确认报文段丢失或者出错,从而导致服务器端不能正常关闭。
-
强缓存和弱缓存
强缓存是指在浏览器发送请求前,先检查本地缓存中是否存在可用的资源副本。如果存在,并且该资源没有过期,服务器将返回一个特定的响应头,告诉浏览器直接使用本地缓存,而不需要向服务器发送请求。这样可以大大减少网络传输,提高页面加载速度和服务性能。弱缓存是指在浏览器发送请求后,服务器会先验证该资源是否被修改过,如果未被修改,则返回一个特定的响应头,告诉浏览器可以使用本地缓存。但与强缓存不同的是,即使缓存过期了,浏览器仍然会向服务器发送一个请求进行验证。
- 强缓存不需要与服务器交互,直接从本地缓存中获取资源,速度快。
- 弱缓存需要与服务器交互,通过验证判断资源是否修改,如果未修改则使用本地缓存。
- 强缓存的优先级高于弱缓存,即如果同时设置了强缓存和弱缓存的响应头,浏览器会首先检查强缓存是否可用。
- 如果强缓存失效,浏览器会发送请求到服务器进行验证,如果通过验证,则服务器会返回新的资源给浏览器,并在响应头中携带新的缓存策略。
- 弱缓存通常配合强缓存一起使用,用于提供更细粒度的缓存控制。
-
强缓存和协商缓存
浏览器缓存的特点:-
浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识
-
浏览器每次拿到返回的请求结果都会将该结果和缓存标识存入浏览器缓存中
根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强制缓存和协商缓存。
协商缓存
-
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
-
协商缓存主要有以下两种情况:
- 协商缓存生效,返回304
- 协商缓存失效,返回200和请求结果结果
-
-
了解前端安全吗?
前端安全涉及保护 Web 应用程序的前端部分免受各种安全威胁的影响。以下是一些常见的前端安全问题和对策:
- 跨站脚本攻击(XSS): 攻击者通过注入恶意脚本来执行客户端脚本,从而盗取用户信息或篡改页面内容。防御措施包括使用内容安全策略(CSP)、对用户输入进行合理的过滤和转义、使用安全的 JavaScript 框架等。
- 跨站请求伪造(CSRF): 攻击者通过伪造请求,利用用户的登录状态执行恶意操作。防御措施包括使用CSRF令牌、检查Referer头、使用同源策略等。
- 点击劫持: 攻击者通过嵌入透明的 iframe 将目标网站伪装在一个诱人的页面上,诱使用户在不知情的情况下执行恶意操作。防御措施包括使用X-Frame-Options头、JavaScript框架中的防护措施等。
- 敏感数据泄露: 未经适当保护的敏感数据在前端传输或存储中暴露,可能被攻击者窃取。防御措施包括使用HTTPS协议传输数据、不将敏感信息存储在前端、加密存储等。
- 不安全的第三方依赖: 使用不安全的第三方库或组件可能导致安全漏洞。防御措施包括定期更新依赖、审查第三方代码的安全性、使用官方或受信任的库等。
-
cookie了解吗?如何实现cookie?
Cookie是由服务器发送到用户浏览器并存储在用户设备上的小型文本文件,用于跟踪用户的网站活动和存储用户偏好信息。要实现cookie,通常需要在服务器端生成cookie并在HTTP响应头中将其发送给客户端的浏览器,然后浏览器会将cookie存储在用户设备上。之后,每当用户访问相同的网站时,浏览器会在HTTP请求头中将cookie发送回服务器,以便服务器可以根据cookie识别用户并提供个性化的体验。 -
HTTP 状态码
- 1xx:指示信息类,表示请求已接受,继续处理(临时响应)
- 2xx:指示成功类,表示请求已成功接受
- 3xx:指示重定向,表示要完成请求必须进行更进一步的操作
- 4xx:指示客户端错误,请求有语法错误或请求无法实现
- 5xx:指示服务器错误,服务器未能实现合法的请求
常见状态码
【403】表示【服务器拒绝执行客户端的请求】
【404】表示【服务器找不到客户端所请求的资源(网页)】
【304】表示【所请求的资源并未修改(命中协商缓存)
-
介绍下 304 过程
缓存过期后向服务器发起请求验证缓存是否有效,有效的话则返回304。304多出现在对于静态资源的请求上面。对于静态资源来说:
当浏览器第一次发起请求时(请求头中没有If-Modified-Since),server会在响应中告诉浏览器这个资源最后修改的时间(响应头中的Last-Modified)。当你再次请求这个资源时,浏览器会询问server这个资源有没有被修改(请求头中If-Modified-Since)。
如果资源没有被修改,server返回304状态码,浏览器使用本地的缓存文件。 -
HTTP1、HTTP2、HTTP3 的区别
HTTP1.0:
-
浏览器与服务器只保持短暂的连接,浏览器的每次请求都需要与服务器建立一个TCP连接
-
服务器完成请求处理后立即断开TCP连接。
-
简单来讲,每次与服务器交互,都需要新开一个连接
HTTP1.1:
-
引入了持久连接,即TCP连接默认不关闭,在同一个TCP连接里面,客户端可以同时发送多个请求
-
虽然允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的,服务器只有处理完一个请求,才会接着处理下一个请求。如果前面的处理特别慢,后面就会有许多请求排队等着
-
新增了一些请求方法,新增了一些请求头和响应头
HTTP2.0:
- 采用二进制格式而非文本格式
- 多路复用,只需一个连接即可实现并行
- 使用报头压缩,降低开销
- 服务器推送
HTTP3.0: - 是 HTTP/3 中的底层支撑协议,该协议基于 UDP,又取了 TCP 中的精华,实现了即快又可靠的协议。
- 优化性能方法
- 给v-for循环项加上key提高diff计算速度
- 防抖和节流
- 图片大小优化和图片懒加载v-lazy
- 路由懒加载
- 使用计算属性computed,有缓存,性能高
- 如何实现跨域?
相关知识点:
-
通过 jsonp 跨域
-
document.domain + iframe 跨域
-
location.hash + iframe
-
window.name + iframe 跨域
-
postMessage 跨域
-
跨域资源共享(CORS)
-
nginx 代理跨域
-
nodejs 中间件代理跨域
-
WebSocket 协议跨域
我们项目当时使用 CORS 的方式,CORS 是一个 W3C 标准,全称是"跨域资源共享"。CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,因此我们只需要在服务器端配置就行。浏览器将 CORS请求分成两类:简单请求和非简单请求。对于简单请求,浏览器直接发出 CORS 请求。具体来说,就是会在头信息之中,增加一个 Origin 字段。Origin 字段用来说明本次请求来自哪个源。服务器根据这个值,决定是否同意这次请求。对于如果 Origin 指定的源,不在许可范围内,服务器会返回一个正常的 HTTP 回应。浏览器发现,这个回应的头信息没有包含 Access-Control-Allow-Origin 字段,就知道出错了,从而抛出一个错误,ajax 不会收到响应信息。如果成功的话会包含一些以 AccessControl- 开头的字段。
- MVC MVVM区别
MVC指的是 model,view, controller
MVVM 指的是 model ,view, viewModel
mvc和mvvm区别是:1、处理业务的模式不同,MVC里,View是可以直接访问Model,而MVVM是将页面与数据逻辑分离的模式,它把数据绑定工作放到一个JS里去实现;2、处理数据操作不同,MVVM通过数据来显示视图层而不是节点操作。
HTML
- HTML5 新特性有哪些
-
语义化标签
-
音视频处理API(audio,video)
-
canvas / webGL
-
拖拽释放(Drag and drop) API
-
history API
-
requestAnimationFrame
-
地理位置(Geolocation)API
-
webSocket
-
web存储 localStorage、SessionStorage
-
表单控件,calendar、date、time、email、url、search
- HTML5 语义化的优点:
- 在没CSS样式的情况下,页面整体也会呈现很好的结构效果
- 代码结构清晰,易于阅读,
- 利于开发和维护 方便其他设备解析(如屏幕阅读器)根据语义渲染网页。
- 有利于搜索引擎优化(SEO),搜索引擎爬虫会根据不同的标签来赋予不同的权重
CSS
- CSS 选择器及优先级
-
选择器
-
id选择器(#myid)
-
类选择器(.myclass)
-
属性选择器(a[rel=“external”])
-
伪类选择器(a:hover, li:nth-child)
-
标签选择器(div, h1,p)
-
相邻选择器(h1 + p)
-
子选择器(ul > li)
-
后代选择器(li a)
-
通配符选择器(*)
-
-
优先级:
-
!important
-
内联样式(1000)
-
ID选择器(0100)
-
类选择器/属性选择器/伪类选择器(0010)
-
元素选择器/伪元素选择器(0001)
-
关系选择器/通配符选择器(0000)
-
带!important 标记的样式属性优先级最高; 样式表的来源相同时: !important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
- CSS3 新特性
- 过渡
1 | /*所有属性从原始值到制定值的一个过渡,运动曲线ease,运动时间0.5秒*/ |
- 动画
1 | //animation:动画名称,一个周期花费时间,运动曲线(默认ease),动画延迟(默认0),播放次数(默认1),是否反向播放动画(默认normal),是否暂停动画(默认running) |
- 形状转换
1 | //transform:适用于2D或3D转换的元素 |
-
选择器:nth-of-type()
-
阴影 文字阴影: text-shadow: 2px 2px 2px #000;(水平阴影,垂直阴影,模糊距离,阴影颜色) 盒子阴影: box-shadow: 10px 10px 5px #999
-
边框 border-image: url(border.png);
-
背景
-
文字
-
渐变
-
Filter(滤镜)
-
弹性布局、栅格布局、多列布局
-
媒体查询
JavaScript
-
原型链了解吗?
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会通过它的__proto__隐式属性,找到它的构造函数的原型对象,如果还没有找到就会再在其构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。所有的原型对象的__proto__属性都是指向function Object的原型对象。 而function Object的原型对象是不存在__proto__这个属性的,它指向了null,所以原型链的尽头是null。 -
如何获取类的自己的属性,而不是原型链的属性
使用hasOwnProperty()方法来判断属性是否为对象自身属性1
2
3
4
5
6
7
8
9
10
11function iterate(obj) {
let result = [];
for (let key in obj) { //for in遍历obj属性
if (obj.hasOwnProperty(key)) { //判断是否为对象自身属性
result.push(key + ':' + obj[key])
} else {
console.log("0");
}
}
return result
} -
如何区分不同的数据类型,比如说怎么判断元素是数组还是对象?
一共有四种方法:- typeof()对基本数据类型可以判断,遇到引用数据类型不管用
- instanceof()只能用于判断引用数据类型,不能判断基本数据类型
- constructor几乎可以判断基本数据类型和引用数据类型。
- Object.prototype.toString.call()判断,基本没有弊端
-
了解页面优化、工程化吗
页面优化通常涉及优化网页加载速度、性能和用户体验,包括压缩和缩小资源、减少 HTTP 请求、使用缓存、优化图像等方法。
工程化则是指利用工程化工具和流程来提高开发效率和代码质量,例如使用构建工具(如Webpack)、版本控制(如Git)、自动化测试等。 -
new操作的过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25//(1)首先创建了一个新的空对象
//(2)设置原型,将对象的原型设置为函数的 prototype 对象。
//(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
//(4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。
//实现:
function objectFactory() {
let newObject = null,
constructor = Array.prototype.shift.call(arguments),
result = null;
//参数判断
if (typeof constructor !== "function") {
console.error("type error");
return;
}
//新建一个空对象,对象的原型为构造函数的 prototype 对象
newObject = Object.create(constructor.prototype);
//将 this 指向新建对象,并执行函数
result = constructor.apply(newObject, arguments);
//判断返回对象
let flag = result && (typeof result === "object" || typeof result === "function");
//判断返回结果
return flag ? result : newObject;
}
//使用方法
//objectFactory(构造函数, 初始化参数); -
ES6继承了解吗?
TypeScript 支持 ES6 中的类和继承,同时还提供了额外的类型系统和其他特性,使得代码更加健壮和可维护。在 TypeScript 中,你可以使用 ES6 的类和继承语法,并且可以通过类型注解等方式增强代码的可读性和可维护性。 -
什么是闭包,为什么要用它?
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。闭包有两个常用的用途。
闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,我们可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。
函数的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。
其实闭包的本质就是作用域链的一个特殊的应用,只要了解了作用域链的创建过程,就能够理解闭包的实现原理。 -
图片懒加载(腾讯面试)
1 | // 获取所有图片 |
- 介绍一下 js 的节流与防抖?
函数防抖:在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。
1 | function debounce(fn, wait) { |
函数节流: 规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
1 | function throttle(fn, limit) { |
- 数组的常用方法有哪些?
-
join(separator):将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符
-
push():将参数添加到原数组末尾,并返回数组的长度(修改原数组)
-
pop():删除原数组最后一项,并返回删除元素的值;如果数组为空则返回undefined(修改原数组)
-
shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined
-
unshift(): 将参数添加到原数组开头,并返回数组的长度(修改原数组)
-
slice(start,end):可以截取出数组某部份的元素为一个新的数组,有两个必填的参数,第一个是起始位置,第二个是结束位置( 操作时数字减1 ) 原数组不改变
-
splice(start,deleteCount,val1,val2,…):从start位置开始删除deleteCount项,并从该位置起插入。(修改原数组)
-
fill():使用特定值填充数组中的一个或多个元素(修改原数组)
-
filter():过滤,数组中的每一项运行给定函数,返回满足过滤条件组成的数组
-
concat():可以将两个数组合并在一起,如果是使用ES6语法也可以用扩展运算符…来代替
-
indexOf():返回当前值在数组中第一次出现位置的索引
-
lastIndexOf():返回查找的字符串最后出现的位置,如果没有找到匹配字符串则返回 -1。
-
every():判断数组中每一项是否都符合条件
-
some():判断数组中是否存在满足的项
-
includes():判断一个数组是否包含指定的值
-
sort(orderfunction):按指定的参数对数组进行排序(修改原数组)
-
reverse():将数组反序(修改原数组)
-
forEach():循环遍历数组每一项(没有返回值)
-
map():循环遍历数组的每一项(有返回值)
-
copyWithin(): 从数组的指定位置拷贝元素到数组的另一个指定位置中(修改原数组)
-
find(): 返回第一个匹配的值,并停止查找
-
findIndex(): 返回第一个匹配值的索引,并停止查找
-
toLocaleString()、toString():将数组转换为字符串
-
flat()、flatMap():扁平化数组
-
entries() 、keys() 、values():遍历数组
- == 和 === 区别
-
== 和 === 区别
-
== 表示相等 (值相等)
-
===表示恒等(类型和值都要相等)
-
js在比较的时候如果是 == 会先做类型转换,再判断值得大小,如果是===类型和值必须都相等。
-
-
== === 和 Object.is () 区别
-
== 相等,如果两边类型不一致,进行隐式转换后,再比较。+0 和 -0 相等, NaN 不等于任何数
-
=== 严格相等,如果类型不一致,就不相等。 +0 和 -0 相等, NaN 不等于任何数
-
Object.is () 严格相等,+0 和 -0 不相等, NaN 等于自身
-
- script 标签放在 header 里和放在 body 底部里有什么区别?
放在 header 中
你能看到 html 第一时间被加载进来,但页面 body 内容迟迟没有渲染出来。因为在等待 header 标签中 script 脚本的加载,3 秒后,整个页面渲染完成。
放在 body 底部
这次 html 内容第一时间渲染完成,随后等待 js 的加载。
总结:
脚本会阻塞页面的渲染,所以推荐将其放在 body 底部,因为当解析到 script 标签时,通常页面的大部分内容都已经渲染完成,让用户马上能看到一个非空白页面。
另外你能看到多个脚本之间都是异步向服务器请求,他们之间不互相依赖,最终只等待 3 秒,而非 3+3+3 秒。
- async
async
是异步的意思,await
则可以理解为 async wait
。所以可以理解async
就是用来声明一个异步方法,而 await
是用来等待异步方法执行
async
async
函数返回一个promise
对象,下面两种方法是等效的
1 | function f() {return Promise.resolve('TEST'); |
await
正常情况下,await
命令后面是一个 Promise
对象,返回该对象的结果。如果不是 Promise
对象,就直接返回对应的值
不管await
后面跟着的是什么,await
都会阻塞后面的代码
1 | async function fn1 (){ |
上面的例子中,await 会阻塞下面的代码(即加入微任务队列),先执行 async外面的同步代码,同步代码执行完,再回到 async 函数中,再执行之前阻塞的代码
所以上述输出结果为:1,fn2,3,2
Vue
-
知道vue,react吗?有用过吗?
使用过vue,Vue.js 是一个渐进式JavaScript框架。Vue特别注重易用性和灵活性,它允许你以不同的方式逐步采用。Vue的核心库只关注视图层,易于上手,也容易与其他库或已有项目整合。Vue还提供了一个生态系统,支持如路由器、状态管理和构建工具等高级功能。采用MVVM框架,我们只需要关注对数据的修改就好,提供大量api,减少我们对dom的直接操作。同时提供虚拟dom,减轻页面渲染压力。 -
Vue的生命周期?
Vue实例从开始创建、初始化数据、编译模版、挂载Dom和渲染、更新和渲染、卸载等一系列过程就是Vue的生命周期。在这个过程中会调用beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed几个钩子函数,从而在不同的阶段运行代码。
此外如果使用了keep-alive组件还可以激活beforeActive和actived -
Vue双向数据绑定原理
vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图,从而实现数据双向绑定。 -
V-if和V-show的区别?
v-show操作的是DOM元素的display属性,有更高的初始渲染开销;v-if操作的是DOM元素的创建和销毁,有更高的切换开销;因此,频繁的切换用v-show,切换较少用v-if。 -
谈谈你对Vuex的理解?
Vuex是一个专门为Vue.js开发的状态管理模式,vuex的应用核心就是store仓库,Store基本上就是个容器,包含着应用中大部分的state状态;Vuex的状态存储是响应式的,改变store中的状态的唯一途径就是通过commit(提交)mutation,方便跟踪每一个状态的变化; -
nextTick 做什么用的?
Vue.nextTick用于延迟执行一段代码,它接受2个参数(回调函数和执行回调函数的上下文环境),如果没有提供回调函数,那么将返回promise对象). -
Vue2和Vue3的区别?
Vue.js是一个流行的JavaScript框架,用于构建用户界面和单页应用程序。Vue2和Vue3是该框架的两个主要版本,它们之间存在一些重要差异:
- 响应性系统:Vue3使用了一个全新的响应性系统,基于ES6的Proxy,相较于Vue2使用的Object.defineProperty,提供了更好的性能和内存效率。这意味着Vue3可以更有效地追踪数据变化,并且支持Map, Set等更多种类的数据结构。
- 组合式API:Vue3引入了Composition API,这是一种新的编写组件的方式,提供了更多的灵活性和可重用性,特别适合于大型应用或更复杂的组件结构。相比之下,Vue2主要使用Options API,这是一种更简单直观的方式来组织组件。
- 性能改进:Vue3提供了更高的性能,包括更小的包大小、更快的冷启动时间和更快的更新速率。这得益于框架的优化,如树摇(tree-shaking)支持、静态树提升和静态属性提升等。
- TypeScript支持:Vue3从一开始就考虑了对TypeScript的支持,使得开发人员可以更容易地使用TypeScript来编写Vue应用程序。而Vue2则需要额外的配置来支持TypeScript。
- 新的内置组件和功能:Vue3引入了新的内置组件和功能,如Fragment, Teleport, 和Suspense,这些都是为了提升开发体验和应对现代前端开发的需求。
- 更好的模板和JSX支持:Vue3提供了更好的模板编译优化和更强的JSX支持,使得开发人员可以在Vue文件中更灵活地使用JSX。
- 变化侦测:在Vue3中,由于Proxy的使用,数组索引和Map等集合的变化能够被自动侦测到,这在Vue2中是做不到的。
-
什么是虚拟DOM
实际上它只是一层对真实
DOM
的抽象,以JavaScript
对象 (VNode
节点) 作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实环境上在
Javascript
对象中,虚拟DOM
表现为一个Object
对象。并且最少包含标签名 (tag
)、属性 (attrs
) 和子元素对象 (children
) 三个属性,不同框架对这三个属性的名命可能会有差别 -
vue的diff算法
Vue.js 使用 Virtual DOM 和 diff 算法来高效地更新 DOM。这是 Vue.js 在处理数据变化时的核心机制之一。Vue.js 的 diff 算法在实现上会尽可能地减少对真实 DOM 的操作,从而提高性能。
Diff 算法主要分为以下几个步骤:
- 生成虚拟 DOM 树: 当数据发生变化时,Vue.js 会生成新的虚拟 DOM 树。
- 比较新旧虚拟 DOM 树: Vue.js 会逐层比较新旧虚拟 DOM 树的节点,找出需要更新的部分。
- 更新差异节点: 找出需要更新的部分后,Vue.js 会针对这些节点进行更新操作,例如修改文本内容、属性或者替换子节点。
- 最终更新到真实 DOM: 更新后的虚拟 DOM 树会被渲染成真实 DOM,并替换掉旧的 DOM 树,完成视图的更新。
-
computed和watch
(1)computed 是计算一个新的属性,并将该属性挂载到 Vue 实例上,而 watch 是监听已经存在且已挂载到 Vue 实例上的数据,所以用 watch 同样可以监听 computed 计算属性的变化。
(2)computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问computed 属性,才会计算新的值。而 watch 则是当数据发生变化便会调用执行函数。
(3)从使用场景上说,computed 适用一个数据被多个数据影响,而 watch 适用一个数据影响多个数据。
- keep-alive
如果你需要在组件切换的时候,保存一些组件的状态防止多次渲染,就可以使用 keep-alive 组件包裹需要保存的组件。
当我们使用 keep-alive 的时候,还有两个钩子函数,分别是 activated 和 deactivated 。用keep-alive 包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated 钩子函数,命中缓存渲染后会执行 actived 钩子函数。
- Title: front-end-interview-preparation
- Author: Charles
- Created at : 2024-03-04 10:35:10
- Updated at : 2024-04-11 14:35:01
- Link: https://charles2530.github.io/2024/03/04/front-end-interview-preparation/
- License: This work is licensed under CC BY-NC-SA 4.0.