React前端面试题

React

1.props和state相同点和不同点?render方法在哪些情况下会执行?

不同点:

Props(属性)是从父组件传递给子组件的,组件内部无法直接修改 值。Props是只读的。用于存储组件外部的数据,应该被视为不可变的。是由父组件传递下来的,遵循单向数据流的原则。

State(状态)是组件内部管理的数据,可以通过setState()方法进行修改。State是可变的。用于存储组件内部的状态数据,可以在组件内部进行修改。通常用于存储用户输入、组件特定的数据或需要在组件内部更新的数据。

相同点:

都用于存储和管理组件中的数据

都可以用于将数据从父组件传递给子组件

当Props或State发生变化时,都可以触发组件的重新渲染

Props和State都可以在组件的render方法中访问,并用于渲染动态内容

Render执行:

组件首次挂载到DOM时会调用render方法进行初始渲染。

当组件的props或state发生变化时,会触发组件的重新渲染,即再次调用render方法。

当父组件重新渲染时,子组件也会重新渲染,即调用子组件的render方法

2.shouldComponentUpdate有什么作用?

ShouldComponentUpdate是React组件生命周期方法之一,用于控制组件是否进行重新渲染。返回一个布尔值,表示组件是否应该重新渲染

方法的作用是优化组件的性能。每当组件的props或state发生变化时,React都会重新渲染组件。有时候,组件的props或state变化并不会影响到组件的输出,
可以通过重写shouldComponentUpdate方法来避免不必要的重新渲染,从而提高性能。

根据组件的props和state的变化情况进行逻辑判断,返回一个布尔值来决定是否重新渲染组件。如果返回false,组件将不会进行重新渲染,而是直接使用之前的渲染结果。

3.说说React中的虚拟dom?在虚拟dom计算的时候diff和key之间有什么关系?

虚拟DOM(Virtual DOM)是React中的一个概念,它是一个轻量级的JavaScript对象,用于表示真实DOM的抽象层。React使用虚拟DOM来提高性能和效率

关系:
diff算法是用于比较两个虚拟DOM树之间的差异,并确定需要更新的部分。它通过一种高效的算法来比较节点的类型、属性和子节点等信息,以确定需要更新或重新渲染的部分。
key属性是在虚拟DOM的渲染中用于标识唯一子元素的属性。在虚拟DOM的比较过程中,React使用key属性来追踪组件及其子元素的身份,以便更准确地确定哪些元素需要更新。
使用合适的key可以帮助React在diff算法中更准确地确定元素的插入、移动和删除操作

工作原理:

当组件状态发生变化时,React会创建一个新的虚拟DOM树,表示组件在新状态下应该呈现的样子。
React将新的虚拟DOM树与之前的虚拟DOM树进行比较,找出两者之间的差异(即diff算法)。
根据差异,React会将需要更新的部分应用到真实DOM中,只更新发生变化的部分,而不是整个DOM树。

4.react新出来两个钩子函数是什么?和删掉的will系列有什么区别?

分别为getDerivedStateFromProps(从props中得到衍生的state)和getSnapshotBeforeUpdate。

区别:

1、componentWillMount中可能需要做的事(一些数据初始化的操作就应该放在这个钩子中处理),constructor与componentDidMount也能做,甚至做的更好,此方法被废弃。
2、componentWillReceiveProps实际行为与命名并不相符,由于不稳定性已由getDerivedStateFromProps代替;
3、而componentWillUpdate同等理由被getSnapshotBeforeUpdate代替

5.React的props.children使用map函数来遍历会收到异常显示,为什么?应该如何遍历?

使用map函数遍历props.children时,如果props.children只包含一个子节点,会收到一个异常显示, 在这种情况下,props.children将不是一个数组,而是一个单独的React元素。

两种方法:
使用React.Children.map:React提供了React.Children.map方法来遍历props.children,无论props.children是单个React元素还是多个React元素,都能正常工作。用法类似于Array.map,可以对每个子元素进行操作,返回一个新的数组
将props.children转换为数组:可以使用Array.from或展开运算符[…]将props.children转换为一个数组,然后再使用map函数进行遍历

6.React组件之间如何通信?

父传子:在父组件的子组件标签上绑定一个自定义属性,通过属性值传递给子组件,子组件使用props接收
子传父:在父组件的子组件标签上绑定一个自定义函数,通过这个函数的回调函数进行传值,传递给父组件
兄弟组件传值:通过子组件传递给一个公共(父组件)组件,然后进行父传子,子传父一系列操作即可
消息订阅与发布:订阅者监听事件,并且做出反应,然后发布者发布信息,通过event方法获取到数据,当发布者修改数据后,监听者也可以及时获取最新数据
全局管理状态:通过redux这种全局管理状态工具进行通信,这种工具会维护一个全局状态中心store,并根据这种状态产生不同的事件

7.说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?

@reduxjs/toolkit是Redux官方提供的一个工具集,旨在简化和优化Redux的使用方式
区别:
react-redux是一个与React结合使用Redux的官方库。提供了用于将Redux与React组件进行连接的connect函数和组件。react-redux帮助管理React组件与Redux之间的数据流动,使得Redux的状态可以在React组件中进行访问和更新。

@reduxjs/toolkit是一个与Redux结合使用的工具集,用于简化和优化Redux的使用方式。它提供了一些工具和API,帮助开发者更轻松地编写和组织Redux代码,减少样板代码的编写,并提供了一些约定和默认配置。

react-redux和@reduxjs/toolkit可以一起使用,@reduxjs/toolkit提供的简化和优化工具可以与react-redux的连接机制结合使用,进一步简化Redux在React应用中的使用和管理

8.React render方法的原理,在什么时候会触发?

原理:

首次渲染:当组件被挂载到DOM时,React会调用组件的render方法,获取组件的输出内容。render方法返回一个React元素(或者null),描述了组件应该如何在DOM中呈现。

数据更新:当组件的props或state发生变化时,React会重新调用组件的render方法,获取组件新的输出内容。React通过比较前一次渲染的输出和当前的输出,找出差异并更新DOM,从而实现局部更新,而不是重新渲染整个组件。

虚拟DOM比较:在进行更新时,React使用虚拟DOM(Virtual DOM)进行比较,而不是直接操作真实DOM。React会将新的虚拟DOM树与之前的虚拟DOM树进行比较,找出两者之间的差异。然后,React会将差异应用到真实DOM上,只更新发生变化的部分,从而提高性能和效率

触发:

组件首次渲染:当组件被挂载到DOM时,会调用组件的render方法进行首次渲染。

组件的props或state发生变化:当组件的props或state发生变化时,React会重新调用组件的render方法,获取新的输出内容,并进行DOM的更新。

JavaScript

1.谈谈你对immutable.js的理解?

Immutable.js是一个JavaScript库,用于处理不可变(Immutable)数据结构。它提供了一组不可变的数据类型,如List、Map、Set等,以及一些操作这些数据类型的方法。Immutable.js的核心思想是不直接修改数据,而是通过创建新的不可变数据来实现数据的更新和变化

理解:

不可变性:Immutable.js的主要概念是不可变性,即数据一旦创建就不可更改。每次对Immutable.js数据进行修改,都会返回一个新的不可变数据,而不是直接修改原始数据。这种不可变性确保了数据的稳定性和可预测性,避免了一些常见的数据修改问题。

持久化数据结构:Immutable.js的数据结构是持久化的,意味着在对数据进行修改时,原始数据仍然保持不变。Immutable.js使用了结构共享(Structural Sharing)的技术,只有被修改的部分会被复制,共享部分则被共享在新数据和原始数据之间,从而节省了内存和性能。

纯函数式操作:Immutable.js提供了一组纯函数式的操作方法,用于对不可变数据进行增删改查等操作。这些操作方法返回新的不可变数据,而不会修改原始数据。通过使用这些操作方法,可以方便地进行数据的更新和变化,同时保持数据的不可变性。

性能优化:Immutable.js通过结构共享和持久化数据结构的特性,可以提供更好的性能。由于只有被修改的部分会被复制,而共享部分可以被多个数据共享,可以减少内存占用和提高性能。

引用相等性:Immutable.js使用引用相等性来判断两个不可变数据是否相等。如果两个不可变数据的引用相同,即它们是同一个对象,那么它们被认为是相等的。这可以简化相等性的判断,避免深度比较。

2.为什么for循环比forEach性能高?

作用域链访问:for循环中的变量直接在当前作用域进行访问,而forEach方法中的回调函数会在一个新的作用域中执行。在forEach中访问外部变量时,需要通过作用域链进行查找,可能会导致性能上的一些开销

优化机制:for循环是一种基本的循环结构,JavaScript引擎在执行for循环时可以进行更多的优化和内联操作,以提高代码的执行效率。而forEach方法是一个高阶函数,它需要遍历数组并针对每个元素执行回调函数,这可能导致额外的函数调用和迭代开销。

可中断性:for循环可以通过break语句或return语句来提前终止循环,而forEach方法无法直接中断循环。这在某些情况下可以提高性能,因为可以避免对不必要的迭代进行操作

3.![] == ![],![] == [],结果是什么?为什么?

1.![] == ![] 首先是!的优先级要比 == 高 所以 先执行两边的 ![] 然后单个的[]是true 加上!取反 也就是false了

然后 第一个 ![] == ![] 也就是等于 false == false 最后返回的是true

2.![] == [] 然后后边的![] == [] 也是因为!优先级高 所以先把左边的变成false == []

然后又因为 两个值相比较 如果有一方的值是布尔值的话 就会把另一方转成数值

然后 [] 转成数值的话 就是 0 然后因为0 = false 所以最后 也是false == false 最后也返回一个true

4.什么是闭包,应用场景是什么?

闭包是指在一个内部函数中访问外部函数作用域的变量的能力。简单来说,闭包就是能够记住并访问定义时的词法环境的函数。

优点

  1. 数据封装:闭包可以将变量和函数封装在内部函数中,隐藏实现细节,只暴露需要的接口。
    2.保持状态:闭包可以保持函数执行时的状态,可以在函数执行完毕后继续访问和使用。
    3.实现函数工厂:闭包可以用于动态生成函数,根据不同的参数生成不同的函数。

缺点

1.内存消耗:闭包会将外部函数的变量和内部函数一起保存在内存中,如果闭包不被正确释放,可能导致内存泄漏。
2.性能影响:闭包的作用域链比普通函数更长,访问外部变量的速度较慢,可能会影响函数的执行效率。
3.可读性和维护性:过多或复杂的闭包嵌套可能会导致代码难以理解、维护和调试

应用场景:

1.保持状态和数据的私有性:闭包可以用于创建私有变量和函数,保护数据的安全性。
2.事件处理程序:闭包可以用于在事件处理程序中保持状态和访问外部变量。
3.模块化开发:闭包可以用于实现模块化开发,将变量和函数封装在私有作用域中,只暴露需要的接口。
4.延迟函数执行:闭包可以用于延迟函数执行,保存函数的状态和参数,在需要时执行函数。

Redux

1.redux本来是同步的,为什么它能执行异步代码?实现原理是什么?中间件的实现原理是什么?

Redux本身是一个同步的状态管理库,但通过中间件来支持执行异步代码。实现原理是基于中间件的概念和Redux的洋葱模型。

具体的实现原理如下:

中间件机制:Redux的中间件机制允许在派发(action dispatch)和到达reducer之间插入额外的逻辑。中间件是一个函数,接收Redux的store对象作为参数,并返回一个函数。这个返回的函数接收next函数作为参数,表示下一个中间件或最终的dispatch函数。

洋葱模型:Redux的中间件采用了洋葱模型(Onion Model)或管道模型(Pipeline Model)。当一个action被派发时,它会依次经过中间件链中的每个中间件。每个中间件都可以在派发到达reducer之前或之后执行一些额外的逻辑,并可以选择将action传递给下一个中间件或最终的dispatch函数。

异步操作:在中间件中执行异步操作时,可以使用异步函数、Promise或通过回调函数来处理。例如,可以在中间件中发起网络请求、读取本地存储等异步操作。当异步操作完成后,可以派发一个新的action,或者不派发action而是执行其他操作。

中间件的执行顺序:中间件的执行顺序是按照它们在中间件链中的顺序依次执行的。每个中间件可以在派发到达reducer之前或之后执行一些额外的逻辑。中间件可以根据需要决定是否调用next函数,从而控制派发过程的流程。

通过使用中间件,Redux可以在派发和到达reducer之间执行额外的逻辑,从而支持执行异步代码。中间件的实现原理是基于函数的链式调用,通过传递next函数和控制流程来实现对派发过程的拦截和处理。这样就使得Redux可以处理异步操作,并提供了一种灵活的扩展机制。

2.redux中同步action与异步action最大的区别是什么?

同步action是一个简单的对象,描述了发生了什么类型的事件,并携带一些数据。它会立即被派发给Redux的store,通过reducer更新应用的状态。同步action的处理是立即执行的,不涉及任何异步操作。

异步action是一个函数,通常称为thunk函数。异步action可以执行异步操作,例如发起网络请求、读取本地存储等。它可以在异步操作完成后,再派发一个同步action,用于更新应用状态。异步action的处理通常需要借助Redux中间件(如Redux Thunk、Redux Saga等)来支持

3.redux-saga和redux-thunk的区别与使用场景?

区别:

实现方式:

Redux-saga使用了ES6的Generator函数来处理异步操作。它通过创建一个单独的线程(称为saga),在该线程中监听Redux的action,并以声明式的方式处理异步操作。Saga使用了类似于同步代码的写法,但实际上是通过yield关键字来暂停和恢复异步操作

Redux-thunk是一个函数,允许在Redux中派发函数类型的action,不仅仅是简单的对象。当派发一个函数类型的action时,Redux-Thunk会拦截该action,并执行该函数,可以在函数中执行异步操作,并在异步操作完成后手动派发一个同步的action来更新状态

复杂度和灵活性:

Redux-Thunk:相对较简单,适用于处理相对简单的异步操作,如网络请求或延迟操作。它可以直接派发函数类型的action,但在处理复杂的异步流程时可能需要编写更多的样板代码。

Redux-Saga:提供了更高级的抽象,用于处理复杂的异步流程和副作用。它可以处理各种异步操作,如网络请求、轮询、取消操作等,提供了更灵活的控制流程和副作用管理的能力

使用场景:
Redux-Thunk:适用于简单的异步操作,如发起简单的网络请求、处理表单提交等。它的学习曲线较低,适合小型项目或需要快速实现异步逻辑的场景。
Redux-Saga:适用于复杂的异步流程,如处理多个相互依赖的请求、处理WebSocket连接、处理复杂的状态同步逻辑等。它提供了更高级的控制流程和副作用管理的能力,适合大型项目或需要处理复杂异步逻辑的场景

4.在使用redux过程中,如何防止定义的action-type的常量重复?

统一管理:将所有的action-type常量集中管理,可以创建一个单独的文件或模块,用于定义和导出所有的action-type常量。这样可以确保所有的action-type常量都在同一个地方定义,避免重复定义。

命名空间:在定义action-type常量时,可以使用命名空间来避免重复。

唯一性检查:可以编写脚本或工具来检查所有的action-type常量,确保没有重复定义。可以通过遍历所有的定义文件,检查常量的唯一性,并给出警告或错误提示。

使用工具库:可以使用一些工具库来帮助管理和防止action-type常量的重复。例如,可以使用redux-actions库来自动生成action-type常量,它可以自动根据action的名称生成唯一的常量,并提供一些辅助函数来简化action的定义和处理。

服务器

1.CDN的特点及意义?

CDN(Content Delivery Network)是一个分布式的网络架构,用于提供高效的内容分发服务

特点:

分布式部署:CDN采用分布式的服务器网络,将内容分发到离用户更近的边缘节点,减少网络延迟和提高访问速度。
缓存机制:CDN通过在边缘节点缓存静态内容,减轻源服务器的负载,提高响应速度。
高可用性:CDN具有高可用性,即使某个节点发生故障,其他节点仍然可以继续提供服务。
负载均衡:CDN可以根据用户的位置和网络状况,智能地选择最优的节点提供服务,实现负载均衡。

意义:

提高用户访问速度:CDN通过将内容分发到离用户更近的边缘节点,减少网络延迟,提高用户访问速度和体验。
减轻源服务器负载:CDN通过在边缘节点缓存静态内容,减轻源服务器的负载,提高源服务器的性能和可靠性。
改善网络传输效率:CDN可以优化网络传输路径,减少网络拥塞,并通过压缩和优化内容来减小传输的数据量。
提供高可用性和可靠性:CDN的分布式架构和负载均衡机制可以提供高可用性和可靠性,即使某个节点发生故障,其他节点仍然可以提供服务。
降低网络成本:通过使用CDN,可以减少网络传输流量,降低网络成本。

CSS

1.谈谈你是如何做移动端适配的?

使用响应式布局:使用CSS的媒体查询(Media Queries)来适配不同的设备和屏幕尺寸。

使用Viewport单位:使用Viewport单位(如vw、vh)来代替传统的像素单位(px),以相对于视口的宽度或高度进行布局和尺寸计算

弹性布局:使用Flexbox或Grid布局来实现弹性和自适应的页面布局。这些布局方式可以根据屏幕尺寸和容器大小自动调整元素的位置和大小。

图片适配:使用响应式图片或使用CSS的max-width属性来确保图片在不同屏幕尺寸下自适应。可以使用srcset和sizes属性来提供不同尺寸和分辨率的图片资源。

使用移动端优化的CSS框架:使用一些经过移动端优化的CSS框架,如Bootstrap、Ant Design Mobile等,可以提供一些移动端适配的组件和样式。

测试和调试:使用模拟器、真机调试和响应式设计工具进行测试和调试,确保页面在各种设备和屏幕尺寸下的正常显示和交互。

2.移动端1像素的解决方案?

使用CSS的border属性:通过设置元素的border属性,将其宽度设置为1像素,配合缩放比例进行调整。例如,可以使用border: 1px solid #000;来创建一个1像素的边框。结合媒体查询和缩放比例进行适配。

使用伪元素和缩放:使用伪元素(::before或::after)来创建一个1像素的伪元素,并通过缩放来调整其显示。可以使用transform: scaleY(0.5);来将伪元素的高度缩放为原来的一半。

使用特定的CSS库或工具:有一些专门解决移动端1像素问题的CSS库或工具可供选择,如border.css、postcss-px-to-viewport等。这些工具提供了更方便的解决方案,可以自动转换1像素的边框或线条。

使用SVG或Icon Font:使用矢量图形(SVG)或Icon Font来绘制1像素的边框或线条。矢量图形可以无损放大和缩小,保持清晰度。Icon Font可以使用字体图标库中的1像素图标来绘制线条

3.弹性盒中的缩放机制是怎样的?

弹性盒(Flexbox)布局是一种用于创建灵活的、自适应的页面布局的CSS布局模型。在弹性盒中,缩放(flex shrink)机制用于控制弹性盒子内项目的缩小行为
在弹性盒中,每个项目都具有flex-shrink属性,用于确定项目在空间不足时是否要缩小以及缩小的比例。flex-shrink属性接受一个非负整数值,默认值为1。

工作原理:
弹性盒中的项目根据其flex-shrink属性值进行排序。较大的flex-shrink值的项目将优先缩小。

当弹性盒的容器空间不足以容纳所有项目时,浏览器会根据项目的flex-shrink属性值来决定各个项目的缩小比例。

缩小比例的计算是根据项目的flex-shrink属性值进行的。如果所有项目的flex-shrink值都相等,则它们将等比例缩小。如果某个项目的flex-shrink值为0,则该项目不会缩小,其他项目将按比例进行缩小

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值