# 1.说说React生命周期中有哪些坑?为什么要移除will相关生命周期?
在React生命周期中,有几个常见的坑需要注意:
1.不正确使用componentDidMount和componentDidUpdate:应该尽量避免在这里进行复杂的操作,可以考虑使用异步操作或放在其他生命周期中处理
2.避免频繁使用setState:如果频繁调用setState可能导致性能问题
3.不要直接修改this.state:应该避免直接修改组件状态的方式,而是使用setState函数来更新状态。
移除will相关的生命周期函数得主要原因是:
1.React团队认为这些函数的命名容易误导开发者,并且可能导致一些问题
2.在17版本中标记will相关的生命周期函数为过时
3.弃用will相关的生命周期函数是为了提升开发者的开发体验和避免潜在的问题
# 2.说说Real diff算法是怎么运作的,从tree层到component层到element层分别讲解?
Real-DOM Diff算法,通常称为Virtual DOM Diff算法,是React使用的一种高效的算法,用于比较两个虚拟DOM树(Virtual DOM Tree)之间的差异,并最小化对实际DOM的更新,从而提高性能。这个算法分为三个层次:Tree层、Component层、Element层。
1. Tree层:在Tree层,Real-DOM Diff算法比较两个虚拟DOM树的根节点。它首先检查两个根节点是否具有相同的类型(例如,两者都是div元素),如果类型相同,则进一步比较其属性。如果类型和属性都相同,React会认为这两个根节点是相同的,不需要进行任何更新。如果类型不同或属性不同,React将认为需要替换整个根节点,从而触发实际DOM的更新。
2. Component层:在Component层,React比较两个虚拟DOM树中的组件(Component)。React会递归地遍历组件的子节点,并比较它们之间的差异。如果两个组件的类型相同,React会继续比较它们的属性和子组件。如果属性相同,但子组件不同,React会递归比较子组件。如果属性不同,React将认为需要更新该组件及其子组件。这样,React会在尽可能深的层次上查找差异,以最小化实际DOM的更新。
3. Element层:在Element层,React比较两个虚拟DOM树中的叶子元素(Element)。React会比较元素的类型、属性和文本内容。如果这些都相同,React将认为两个元素是相同的,不需要更新。如果有差异,React将更新实际DOM以反映这些差异。
Real-DOM Diff算法通过这三个层次的比较,可以高效地找到需要更新的部分,并最小化实际DOM的变更。它还可以在Diff过程中生成一系列的DOM操作指令(例如增加节点、删除节点、更新节点属性等),然后将这些指令批量执行,从而进一步提高性能。
总的来说,Real-DOM Diff算法是React的核心之一,它使React能够高效地管理和更新DOM,提供了快速响应用户交互的能力,同时尽可能减少了不必要的DOM操作,提高了性能。
# 3.调和阶段setState干了什么?
在React中,`setState` 是用来更新组件的状态(state)的方法之一。当调用 `setState` 时,React 将触发组件的重新渲染,以反映新的状态。React会将新的状态与旧的状态合并,而不是完全替换它。
在React的生命周期中,`setState` 调用的时机对于组件的更新非常重要。通常,`setState` 调用会在组件的更新阶段之后触发,而不会立即生效。React会将多个 `setState` 调用合并成一个更新,以提高性能。
React 的组件更新过程大致如下:
1. 组件接收到新的 props 或调用了 `setState`。
2. React 会计划进行一次更新。
3. React 在下一个“调和阶段”(Reconciliation Phase)中比较虚拟DOM树的差异,以找出需要更新的部分。
4. React 更新真实DOM以反映新的虚拟DOM。
5. 组件的生命周期方法被调用(例如,`componentDidUpdate`)。
在上述过程中,`setState` 的调用触发了更新,但实际的DOM更新在下一个调和阶段中完成。
这种异步更新的机制是为了提高性能,因为它可以合并多个状态更新,减少不必要的DOM操作。但需要注意,`setState` 调用并不会立即改变组件的状态,因此如果你想在状态更新后执行某些操作,应该在 `componentDidUpdate` 生命周期方法中进行。
# 4.CSS3的新特性都有哪些?
CSS3(Cascading Style Sheets 3)引入了许多新特性,以增强网页设计的灵活性和功能。以下是一些CSS3的新特性:
1. **选择器的增强**:CSS3引入了众多新的选择器,如通用兄弟选择器(`~`)、属性选择器(`[attr]`)、伪类选择器(`:nth-child`)、伪元素选择器(`::before`和`::after`)等。这些选择器提供更多的精确控制和灵活性。
2. **盒子模型**:CSS3引入了`box-sizing`属性,允许开发者控制盒子模型的计算方式,包括`content-box`和`border-box`。
3. **圆角边框**:使用`border-radius`属性,可以轻松创建圆角边框,而不再需要使用背景图片或其他技巧。
4. **阴影效果**:引入了`box-shadow`属性,可以为元素添加投影效果。
5. **渐变**:CSS3支持线性渐变(`linear-gradient`)和径向渐变(`radial-gradient`),使背景颜色和图片渐变变得更加容易。
6. **多列布局**:`column-count`和`column-gap`等属性允许创建多列布局,使文本流更具吸引力。
7. **媒体查询**:媒体查询允许根据不同的设备、屏幕尺寸和特性来应用不同的CSS样式,从而实现响应式设计。
8. **动画和过渡**:CSS3引入了`@keyframes`规则和`transition`属性,用于创建动画和过渡效果,而不需要JavaScript。
9. **变换(Transforms)**:CSS3的`transform`属性允许对元素进行旋转、缩放、倾斜和平移操作。
10. **过渡(Transitions)**:`transition`属性允许在状态改变时平滑地过渡,以实现流畅的效果。
11. **2D和3D转换**:CSS3支持二维和三维的元素变换,包括旋转、缩放、移动和透视。
12. **字体处理**:引入了`@font-face`规则,允许使用自定义字体。
13. **多重背景图片**:可以为元素添加多个背景图像,通过逗号分隔它们。
14. **伪类选择器**:CSS3引入了众多伪类选择器,如`:nth-child`、`:not`等,用于选择DOM元素的不同状态或位置。
15. **Grid布局**:CSS Grid布局是一个强大的网格系统,用于创建复杂的布局结构。
这些特性使CSS更加强大和灵活,使开发者能够更轻松地实现各种设计和布局效果,同时提高了响应性和性能。不同浏览器对这些特性的支持程度可能有所不同,因此在使用时需要考虑兼容性。
# 5.React合成事件的原理,有什么好处和优势?
React合成事件是React框架提供的一种事件处理机制,用于处理DOM事件。合成事件是一种在原生浏览器事件系统之上构建的抽象,它有以下原理、好处和优势:
**原理**:
1. **事件委托**:React利用事件委托的原理,将所有事件监听器挂载到顶层容器(通常是`document`),而不是每个元素上。这样可以减少DOM元素上的事件监听器数量,提高性能。
2. **事件池**:React使用事件池来管理事件对象,这意味着事件对象在事件处理函数执行完毕后会被重用,而不是立即销毁。这减少了垃圾回收的压力,提高了性能。
**好处和优势**:
1. **性能优化**:React合成事件的事件委托和事件池机制有助于减少内存和性能开销。通过减少事件监听器数量和减少垃圾回收,提高了应用程序的性能。
2. **跨浏览器兼容性**:React合成事件屏蔽了不同浏览器之间的差异,使开发者不必担心浏览器兼容性问题。React会处理不同浏览器的事件差异,以确保一致的行为。
3. **事件委托**:React的事件委托机制允许你在组件树中处理事件,而不必在每个组件上都添加事件监听器。这样可以更容易管理事件处理逻辑,减少重复的代码。
4. **性能监测和调试**:React提供了开发者工具,可以用于监测和调试合成事件。你可以查看事件的详细信息,包括事件类型、事件目标和事件处理函数,以便更容易调试和分析应用程序的行为。
总的来说,React合成事件提供了一种高性能、一致性和易于调试的事件处理机制,使开发者可以更专注于应用程序的逻辑,而不必过多关注浏览器差异和性能优化。这有助于提高React应用程序的开发效率和用户体验。
# 6为什么react元素有一个$$type属性?
React元素(React elements)通常是用`React.createElement()`或JSX语法创建的,它们是描述虚拟DOM树的轻量对象。React元素对象中的`$$type`属性是内部React实现的一个私有属性,用于标识元素的类型。这个属性的名称以`$$`开头,表明它是一个私有属性,不应该被应用程序代码直接访问或修改。
React使用`$$type`属性来表示元素的类型,通常是一个字符串,表示HTML元素的标签名(如`div`、`p`等)或React组件的类型(如自定义组件)。这有助于React在虚拟DOM的比较过程中快速确定元素的类型,以便进行高效的更新和渲染。
应用程序代码通常不需要访问或使用`$$type`属性,因为它是React内部的实现细节。开发者应该专注于使用React提供的公共API来创建、更新和渲染元素,而不必担心`$$type`属性。
在React的官方文档中,`$$type`属性是私有的,并没有被正式记录在文档中,因此不建议开发者在自己的应用程序代码中使用它。如果你需要获取元素的类型,可以使用`type`属性或`element.type`来访问。
# 7.说说你对fiber架构的理解?解决了什么问题?
React Fiber(又称React 16 Fiber)是React框架的重大改进,引入了一种新的协调算法,旨在解决React渲染和调度的性能问题。Fiber架构主要解决了以下几个问题:
1. **渲染中断和调度优先级**:传统的React调度算法是递归的,当组件树很深或组件数量很多时,可能导致渲染操作阻塞主线程,引起页面卡顿。React Fiber引入了可中断的渲染,将渲染过程分解为多个小任务,每个任务都有一个优先级。这样可以更好地控制渲染的优先级,允许浏览器在渲染期间响应用户交互。
2. **增量更新**:传统的React在更新时会进行完整的虚拟DOM比较,然后更新整个组件树。React Fiber引入了增量更新的能力,使得React可以只更新发生变化的部分,从而减少不必要的工作,提高性能。
3. **并行处理**:React Fiber引入了并行处理的概念,允许React在多个任务之间切换,从而更充分地利用多核CPU。这可以加速渲染操作,特别是在处理大型应用程序或复杂组件树时。
4. **可终止和可恢复的渲染**:Fiber允许React在渲染任务中间被终止,而不会破坏整个渲染过程。这对于处理大型列表或复杂UI场景非常有用。一旦浏览器有时间,React可以继续之前被中断的渲染任务。
5. **更好的动画支持**:React Fiber提供了更好的动画支持,可以更精确地控制动画和布局过程。这有助于创建流畅的用户体验。
6. **自定义渲染器**:Fiber的架构允许开发者创建自定义渲染器,以适应不同的平台和环境,如React Native、VR应用等。
总的来说,React Fiber的目标是改进React的渲染性能,使其更适用于大型和复杂的应用程序,提供更好的用户体验,同时提高了React的可扩展性,以适应各种不同的应用场景。这一架构的引入使得React更灵活、高效和强大。
# 8.短轮询、长轮询和 WebSocket 间的区别?
短轮询、长轮询(Comet),和 WebSocket 是用于实现实时通信的不同技术和协议,它们在工作原理和应用场景上有一些重要区别。
1. **短轮询(Short Polling)**:
- 工作原理:客户端定期向服务器发送HTTP请求,询问是否有新数据可用。
- 应用场景:适用于需要实时数据更新,但对延迟和网络带宽要求不高的应用。通常会产生频繁的HTTP请求。
- 优点:简单,适用于大多数浏览器和服务器。不需要特殊的协议支持。
- 缺点:产生较多的网络流量,可能会导致高延迟。
2. **长轮询(Long Polling)**:
- 工作原理:客户端向服务器发送一个HTTP请求,服务器保持请求打开,直到有新数据可用时才响应,然后客户端会立即发送下一个请求。
- 应用场景:适用于需要较低延迟但不能支持WebSocket的应用。减少了HTTP请求次数,但仍然会有一些延迟。
- 优点:较短轮询来说,减少了不必要的HTTP请求。
- 缺点:服务器需要保持连接打开,浏览器需要等待响应,可能会导致资源占用和连接限制。
3. **WebSocket**:
- 工作原理:WebSocket是一种双向通信协议,允许服务器主动向客户端发送数据,而不需要客户端发起请求。通信始终是活跃的连接。
- 应用场景:适用于需要实时、低延迟通信的应用,如聊天应用、实时游戏等。
- 优点:实时、低延迟,减少了不必要的HTTP请求。双向通信使服务器可以主动推送数据。
- 缺点:需要浏览器和服务器支持WebSocket协议,可能需要额外的配置和安全考虑。
总结,短轮询、长轮询和WebSocket都是用于实现实时通信的技术,但它们在性能、延迟、复杂性和应用场景上有不同的权衡。选择哪种技术取决于你的应用需求和支持情况。WebSocket通常是最佳选择,因为它提供了双向通信和低延迟,但如果无法使用WebSocket,则长轮询或短轮询可能是备选方案。
# 9.前端跨域的解决方案?
前端跨域是由于浏览器的同源策略(Same-Origin Policy)引起的,为了保护用户安全,浏览器会限制不同源(协议、域名、端口不同)之间的资源请求。如果你需要在前端处理跨域请求,有以下一些解决方案:
1. **JSONP(JSON with Padding)**:
- JSONP是一种跨域请求的方法,它通过动态添加`<script>`标签来获取数据。服务器返回的数据包装在回调函数中,然后在页面中执行该回调函数,以获取数据。
- 优点:简单易用,可以在不支持CORS的老浏览器上使用。
- 缺点:不支持POST请求,存在安全风险,只能用于获取数据。
2. **CORS(跨域资源共享)**:
- CORS是一种官方的跨域解决方案,需要服务器设置响应头中的`Access-Control-Allow-Origin`等相关字段,以允许特定域名的请求。
- 优点:安全且强大,支持各种HTTP方法,适用于现代浏览器。
- 缺点:需要服务器端支持,不适用于旧版本浏览器。
3. **代理服务器**:
- 前端可以使用自己的服务器作为代理,将跨域请求发送给自己的服务器,然后由服务器代为向目标服务器请求数据,最后将数据传递给前端。这种方式可以绕过浏览器的同源策略。
- 优点:适用于所有浏览器,可以处理复杂的跨域请求。
- 缺点:需要自己的服务器,并且可能会增加服务器负担。
4. **跨文档消息传递(Window.postMessage)**:
- 使用`postMessage` API可以在不同窗口或iframe之间进行跨域通信。前端可以将消息发送到另一个窗口,然后在接收窗口中处理消息。
- 优点:安全,适用于多窗口通信。
- 缺点:需要对方窗口的协助。
5. **JSON Web Tokens(JWT)**:
- JWT是一种用于在不同域之间进行安全身份验证和授权的标准。它可以在不同域之间传递数据,并验证数据的真实性。
- 优点:安全,适用于身份验证和授权。
选择哪种跨域解决方案取决于你的应用需求和目标,以及你的控制权和能力。通常,CORS是最常见和最强大的解决方案,但其他方法也有其用途,根据具体情况选择最适合的方案。
# 10.数组常用方法及作用,至少15个?
1.concat(): 连接两个或更多的数组,并返回结果新数组
2.every(): 检测数值元素的每个元素是否都符合条件
3.filter(): 返回符合条件的数组元素,即过滤掉不符合条件的元素
4.forEach(): 遍历数组中的每个元素并执行回调函数
5.indexOf(): 返回数组中第一个指定元素的索引位置
6.join(): 将所有元素连接成一个字符串
7.lastIndexOf(): 返回数组中最后一个指定元素的索引位置
8.map(): 遍历数组并对每个元素进行操作,最后返回操作后得到的新数组
9.pop(): 删除并返回数组的最后一个元素
10.push(): 向数组末尾添加一个或多个元素
11.reduce(): 对数组中的所有元素执行指定的操作,并将其结果累加到一个单独的值中
12.reverse(): 反转数组中元素的顺序
13.sort(): 对数组中的元素进行排序
14.shift(): 删除并返回数组的第一个元素
15.slice(): 从数组中获取指定范围内的元素