前端相关知识(1)

目录

一、Real diff算法是怎么运行的?

1、Tree层

2.Component层

3.Element层

二、说说React 生命周期中有哪些坑?为什么要移除will相关生命周期?

三、调和阶段setState干了什么?

四、CSS3的新特性都有哪些? 

选择器的增强:

盒子模型

圆角边框

阴影效果

渐变

媒体查询

动画和过渡

2D和3D转换

多重背景图片

五、说说redux的工作流程?

六、React合成事件的原理,有什么好处和优势?

七、为什么 react 元素会有一个$$type属性? 

八、React有哪些优化性能的手段?

九、说说你对fiber架构的理解?解决了什么问题? 

十、说说你对redux中间件的理解?常用的中间件有哪些?实现原理?

十一、如何使用css实现一个三角形,写出两种以上方案得满分。

十二、短轮询、长轮询和websocket的区别?

十三、前端跨域的解决方式? 

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

十五、React render方法的原理,在什么时候会触发?

十六、Redux中同步 action 与异步 action最大的区别? 

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

十八、React 组件之间如何通信?

十九、说说你对受控组件和非受控组件的理解?应用场景?

二十、说说javascript内存泄漏的几种情况?

 结尾


一、Real diff算法是怎么运行的?

Real diff 算法是React使用的一种高效的算法,在更新数据时使用,用于比较两个虚拟DOM树之间的差异,并最小化对实际DOM的更新,从而提高性能。

Real diff可以分为三个阶段:

1、Tree层:

在Tree层,Real diff算法比较两个虚拟DOM树的根节点。它首先检查两个根节点是否具有相同的类型,如果类型相同,则进一步比较其属性。如果类型和属性都相同,React会认为这两个根节点是相同的,不需要进行任何更新。如果类型不同或属性不同,React将认为需要替换整个根节点,从而触发实际DOM的更新。

2.Component层:

在Component层,react比较两个虚拟DOM树种的组件。React会递归的遍历组件中的子节点,并比较它们之间的差异。如果两个组件的类型相同,React会继续比较它们的属性和子节点。如果属性相同,但子组件不同,React会递归比较子组件。如果属性不同,React将认为需要更新该组件及其子组件。这样,React会在尽可能深的层次上查找差异,以最小化实际DOM的更新。

3.Element层

在Element层,React比较两个虚拟DOM树中的叶子元素。React会比较元素的类型、属性和文本内容。如果这些都相同,React将认为两个元素是相同的,不需要更新。如果有差异,React将更新实际DOM以反映这些差异。

二、说说React 生命周期中有哪些坑?为什么要移除will相关生命周期?

在React生命周期中,有几个常见的坑需要注意:

1.不正确使用componentDidMount和componentDidUpdate:应该尽量避免在这里进行复杂的操作,可以考虑使用异步操作或放在其他生命周期中处理

2.避免频繁使用setState:如果频繁调用setState可能导致性能问题

3.不要直接修改this.state:应该避免直接修改组件状态的方式,而是使用setState函数来更新状态。

移除will相关的生命周期函数的主要原因是: 

1.React团队认为这些函数的命名容易误导开发者,并且可能导致一些问题

2.在17版本中标记will相关的生命周期函数为过时

3.弃用will相关的生命周期函数是为了提升开发者的开发体验和避免潜在的问题

三、调和阶段setState干了什么?

在React中,setState 是用来更新组件的状态(state)的方法之一。当调用 setState 时,React 将触发组件的重新渲染,以反映新的状态。React会将新的状态与旧的状态合并,而不是完全替换它。

通常,setState 调用会在组件的更新阶段之后触发,但不会立即生效。React会将多个 setState 调用合并成一个更新,以提高性能。

React 的组件更新过程大致如下:

  1. 组件接收到新的 props 或调用了 setState
  2. React 会计划进行一次更新。
  3. React 在下一个“调和阶段”中比较虚拟DOM树的差异,以找出需要更新的部分。
  4. React 更新真实DOM以反映新的虚拟DOM。
  5. 组件的生命周期方法被调用。

四、CSS3的新特性都有哪些? 

选择器的增强

CSS3引入了众多新的选择器,如通用兄弟选择器(~)、属性选择器([attr])、伪类选择器(:nth-child)、伪元素选择器(::before::after)等。这些选择器提供更多的精确控制和灵活性。

盒子模型

CSS3引入了box-sizing属性,允许开发者控制盒子模型的计算方式,包括content-boxborder-box

圆角边框

使用border-radius属性,可以轻松创建圆角边框,而不再需要使用背景图片或其他技巧。

阴影效果:

引入了box-shadow属性,可以为元素添加投影效果。

渐变

CSS3支持线性渐变(linear-gradient)和径向渐变(radial-gradient),使背景颜色和图片渐变变得更加容易。

媒体查询

媒体查询允许根据不同的设备、屏幕尺寸和特性来应用不同的CSS样式,从而实现响应式设计。

动画和过渡

CSS3引入了@keyframes规则和transition属性,用于创建动画和过渡效果,而不需要JavaScript。

2D和3D转换

CSS3支持二维和三维的元素变换,包括旋转、缩放、移动和透视

多重背景图片

可以为元素添加多个背景图像,通过逗号分隔它们。

五、说说redux的工作流程?

  1. 创建 Store:首先,需要创建一个 Redux Store,用于存储应用的状态。可以使用 createStore 函数来创建 Store,并传入一个 Reducer 函数作为参数。
  2. 定义Reducers:Reducer 是一个纯函数,用于根据动作(Action)来更新状态。每个 Reducer 对应一个状态字段,它接受两个参数:当前状态和动作。根据动作的类型和数据,Reducer 返回新的状态。
  3. 发送 Actions:Actions 是用于描述状态更改的对象,它包含一个类型(type)和一个数据(payload)。可以通过调用 store.dispatch 方法来发送 Actions。
  4. 更新 State:当发送一个 Action 时,Store 会调用相应的 Reducer,并将当前状态和动作作为参数传递给 Reducer。Reducer 返回的新状态将被更新到 Store 中。
  5. 使用 State:可以通过访问 store.getState() 方法来获取当前的应用状态。
  6. 监听 State 更新:可以使用 store.subscribe() 方法来监听 State 的更新。当 State 发生变化时,会触发回调函数。
  7. 使用 Middleware:Middleware 是一种中间件机制,可以在 A6ctions 被发送之前和之后进行额外的操作,例如日志记录、异步操作等。

六、React合成事件的原理,有什么好处和优势?

React合成事件是React框架提供的一种事件处理机制,用于处理DOM事件。合成事件是一种在原生浏览器事件系统之上构建的抽象,它有以下原理、好处和优势:

原理:

  1. 事件委托:React利用事件委托的原理,将所有事件监听器挂载到顶层容器(通常是document)上,而不是每个元素上。这样可以减少DOM元素上的事件监听器数量,提高性能。
  2. 事件池:React使用事件池来管理事件对象,这意味着事件对象在事件处理函数执行完毕后会被重用,而不是立即销毁。这减少了垃圾回收的压力,提高了性能。

好处和优势:

  1. 性能优化:React合成事件的事件委托和事件池机制有助于减少内存和 性能开销。通过减少事件监听器数量和减少垃圾回收,提高了应用程序的性能。
  2. 跨浏览器兼容性:React合成事件屏蔽了不同浏览器之间的差异,使开发者不必担心浏览器兼容性问题。React会处理不同浏览器的事件差异,以确保一致的行为。
  3. 性能监测和调试:React提供了开发者工具,可以用于监测和调试合成事件。你可以查看事件的详细信息,包括事件类型、事件目标和事件处理函数,以便更容易调试和分析应用程序的行为。

七、为什么 react 元素会有一个$$type属性? 

React元素通常是用`React.createElement()`或JSX语法创建的,它们是描述虚拟DOM树的轻量对象。React元素对象中的`$$type`属性是内部React实现的一个私有属性,用于标识元素的类型。这个属性的名称以`$$`开头,表明它是一个私有属性,不应该被应用程序代码直接访问或修改。

React使用$$type属性来表示元素的类型,通常是一个字符串,表示HTML元素的标签名(如divp等)或React组件的类型(如自定义组件)。这有助于React在虚拟DOM的比较过程中快速确定元素的类型,以便进行高效的更新和渲染。

应用程序代码通常不需要访问或使用$$type属性,因为它是React内部的实现细节。开发者应该专注于使用React提供的公共API来创建、更新和渲染元素,而不必担心$$type属性。

在React的官方文档中,$$type属性是私有的,并没有被正式记录在文档中,因此不建议开发者在自己的应用程序代码中使用它。如果你需要获取元素的类型,可以使用type属性或element.type来访问。

八、React有哪些优化性能的手段?

  1. 使用合成事件:使用事件委托,将事件监听器挂载在顶层容器上,而不是每个DOM元素上。这减少了事件监听器的数量,从而减小了内存和性能开销。
  2. 使用React的虚拟DOM:React使用虚拟DOM来比较前后两个状态树,从而最小化对实际DOM的操作。这减少了DOM操作的次数,提高了性能。
  3. 使用列表和键:在渲染列表时,使用唯一的键来标识每个列表项,以帮助React识别添加、删除或重新排序的操作。这有助于React更有效地管理列表的更新。
  4. 避免深层次的嵌套:过多的嵌套组件可能会导致性能问题。尽量保持组件层次扁平,只嵌套必要的组件。
  5. 使用懒加载和代码拆分:将应用程序代码拆分成小块,按需加载,以减小初始加载时间。React懒加载的React.lazy()Suspense功能可用于按需加载组件。
  6. 使用生命周期方法或副作用钩子:合理使用componentDidMountcomponentDidUpdatecomponentWillUnmount等生命周期方法,以及useEffect等副作用钩子,以执行异步操作、订阅和取消订阅等操作。

九、说说你对fiber架构的理解?解决了什么问题? 

 

Fiber 架构是 React 推出的一种新的架构,主要解决了大型应用或复杂组件树的渲染和更新问题,提高了页面的性能和用户交互体验。具体来说,Fiber 架构有以下几个优点:

  1. 异步渲染:Fiber 框架将渲染过程分解成多个小任务,可以在每个任务之间让出主线程,从而实现异步渲染。这样可以提高页面的响应性能,避免页面的卡顿或无响应。
  2. 优先级调度:Fiber 框架引入了任务优先级的概念,可以根据任务的优先级来决定任务的执行顺序。这样可以优先处理一些重要的任务,提高用户交互的体验。
  3. 增量渲染:Fiber 框架可以将渲染过程分解成多个阶段,每个阶段只处理一部分任务,然后让出主线程。这样可以实现增量渲染,即在每个阶段之间可以更新部分组件,从而提高渲染的效率。
  4. 错误边界:Fiber 框架引入了错误边界的概念,可以捕获并处理组件渲染过程中的错误,避免错误导致整个组件树的崩溃。

Fiber架构解决了以下问题:

传统的React架构在执行更新时采用的是递归算法。这种递归算法在更新过程中无法中断,可能导致长时间的JavaScript执行阻塞主线程。而Fiber架构通过引入Fiber数据结构,将递归算法改为迭代算法,使渲染过程可中断和恢复,从而避免了长时间的主线程阻塞。

为了实现整个Diff和Render的流程可中断和恢复,React 16引入了采用单链表结构的Fiber树。Fiber树中的每个节点就是一个工作单元,表示一个虚拟DOM节点。这种数据结构使得React可以更加灵活地调度和中断任务。

十、说说你对redux中间件的理解?常用的中间件有哪些?实现原理?

Redux中间件是一种用于扩展Redux的功能的机制,它允许你在Redux的dispatch过程中添加自定义的逻辑。中间件在Redux应用中的常见用途包括异步操作、日志记录、路由导航、状态持久化等。通过中间件,你可以在action被派发到reducer之前或之后执行一些额外的操作,以满足不同的需求。

Redux中间件的主要原理是基于函数的洋葱模型(Onion Model),它允许你在Redux流程的不同阶段添加自定义逻辑,这些逻辑会按顺序执行。Redux中间件通常由一个函数构成,该函数返回一个函数,这个返回的函数接受store.dispatchstore.getState等参数,然后返回一个新的dispatch函数。这个新的dispatch函数可以拦截、修改、延迟或增强action派发的过程。

常用的Redux中间件有:

  1. redux-thunk:允许你派发函数而不仅仅是普通的action对象,这使得处理异步操作变得容易。当你需要执行异步操作时,可以返回一个函数,该函数接收dispatchgetState作为参数,然后可以在异步操作完成后再次派发action。
  2. redux-saga:基于ES6生成器的中间件,用于处理复杂的异步操作、副作用和并发流。它允许你以声明性的方式管理和监视action的流,处理各种复杂的异步任务。
  3. redux-logger:用于在控制台中记录Redux操作和状态的中间件,用于开发和调试过程。
  4. redux-persist:用于将Redux状态持久化到本地存储,以便应用程序在重新加载时保持状态。
  5. redux-observable:基于RxJS的中间件,用于处理异步操作和副作用。它允许你使用RxJS的强大功能来管理和监视action流。

Redux中间件的实现原理是基于函数的装饰器模式,它通过包装store.dispatch方法,来拦截和处理action。中间件的核心是一个函数,该函数接受store.dispatch作为参数,并返回一个新的函数,这个新函数会在派发action时执行额外的逻辑。这使得中间件可以在不改变Redux核心逻辑的情况下,添加各种自定义功能。

十一、如何使用css实现一个三角形,写出两种以上方案得满分。

你可以使用CSS实现三角形的几种方式,以下是两种常见的方法:

方法一:使用伪元素(::before 或 ::after)

.triangle {

  width: 0;

  height: 0;

  border-left: 50px solid transparent;  /* 左边透明 */

  border-right: 50px solid transparent; /* 右边透明 */

  border-bottom: 87px solid #007bff;  /* 底边实色 */

}

在这个示例中,我们使用伪元素 ::before 或 ::after 创建了一个宽度为0、高度为0的元素,然后通过设置不同边的边框属性来形成一个等腰三角形。

方法二:使用旋转

.triangle {

  width: 0;

  height: 0;

  border-left: 50px solid transparent;  /* 左边透明 */

  border-right: 50px solid transparent; /* 右边透明 */

  border-bottom: 87px solid #007bff;  /* 底边实色 */

  transform: rotate(180deg); /* 旋转180度,使底边朝上 */

}

这种方法与方法一类似,但我们将三角形旋转了180度,使底边朝上,形成一个等腰三角形。

你可以将上述CSS应用于一个HTML元素,例如:

<div class="triangle"></div>

这两种方法都可以用于创建简单的三角形,你可以根据需要进行修改和定制。

十二、短轮询、长轮询和websocket的区别?

短轮询、长轮询,和 WebSocket 是用于实现实时通信的不同技术和协议,它们在工作原理和应用场景上有一些重要区别。

  1. 短轮询(Short Polling)
    • 工作原理:客户端定期向服务器发送HTTP请求,询问是否有新数据可用。
    • 应用场景:适用于需要实时数据更新,但对延迟和网络带宽要求不高的应用。通常会产生频繁的HTTP请求。
    • 优点:简单,适用于大多数浏览器和服务器。不需要特殊的协议支持。
    • 缺点:产生较多的网络流量,可能会导致高延迟。
  2. 长轮询(Long Polling)
    • 工作原理:客户端向服务器发送一个HTTP请求,服务器保持请求打开,直到有新数据可用时才响应,然后客户端会立即发送下一个请求。
    • 应用场景:适用于需要较低延迟但不能支持WebSocket的应用。减少了HTTP请求次数,但仍然会有一些延迟。
    • 优点:较短轮询来说,减少了不必要的HTTP请求。
    • 缺点:服务器需要保持连接打开,浏览器需要等待响应,可能会导致资源占用和连接限制。
  3. WebSocket
    • 工作原理:WebSocket是一种双向通信协议,允许服务器主动向客户端发送数据,而不需要客户端发起请求。通信始终是活跃的连接。
    • 应用场景:适用于需要实时、低延迟通信的应用,如聊天应用、实时游戏等。
    • 优点:实时、低延迟,减少了不必要的HTTP请求。双向通信使服务器可以主动推送数据。
    • 缺点:需要浏览器和服务器支持WebSocket协议,可能需要额外的配置和安全考虑。

十三、前端跨域的解决方式? 

前端跨域是由于浏览器的同源策略引起的,为了保护用户安全,浏览器会限制不同源(协议、域名、端口不同)之间的资源请求。

  1. JSONP(JSON with Padding)
    • JSONP是一种跨域请求的方法,它通过动态添加<script>标签来获取数据。服务器返回的数据包装在回调函数中,然后在页面中执行该回调函数,以获取数据。
    • 优点:简单易用,可以在不支持CORS的老浏览器上使用。
    • 缺点:不支持POST请求,存在安全风险,只能用于获取数据。
  2. CORS(跨域资源共享)
    • CORS是一种官方的跨域解决方案,需要服务器设置响应头,以允许特定域名的请求。
    • 优点:安全且强大,支持各种HTTP方法,适用于现代浏览器。
    • 缺点:需要服务器端支持,不适用于旧版本浏览器。
  3. 代理服务器
    • 前端可以使用自己的服务器作为代理,将跨域请求发送给自己的服务器,然后由服务器代为向目标服务器请求数据,最后将数据传递给前端。这种方式可以绕过浏览器的同源策略。
    • 优点:适用于所有浏览器,可以处理复杂的跨域请求。
    • 缺点:需要自己的服务器,并且可能会增加服务器负担。
  4. JSON Web Tokens(JWT)
    • JWT是一种用于在不同域之间进行安全身份验证和授权的标准。它可以在不同域之间传递数据,并验证数据的真实性。
    • 优点:安全,适用于身份验证和授权。

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

@reduxjs/toolkit是一个Redux官方推荐的工具集,它的主要目的是简化和加速Redux开发流程,提供了一组工具和约定,以减少样板代码和提高开发效率。下面是我对@reduxjs/toolkit的理解以及它与react-redux之间的区别:

@reduxjs/toolkit的特点和理解

  1. Redux简化@reduxjs/toolkit减少了编写Redux的样板代码的工作,包括定义action和reducer,以及配置store。它提供了一个更简洁的方式来创建和组织Redux相关的代码。
  2. 包含Redux工具@reduxjs/toolkit内置了许多有用的Redux工具,如createSlice用于创建Redux模块、configureStore用于配置Redux store,以及createAsyncThunk用于处理异步操作。
  3. 不需要手动处理不变性@reduxjs/toolkit内部使用了Immer库,允许你编写可变的Redux reducer代码,而不需要手动处理深层复制和不变性。这简化了Reducer的编写。
  4. 默认配置@reduxjs/toolkit为你提供了一个合理的默认配置,减少了配置和样板代码的需要。你可以根据需要自定义配置。
  5. 强调最佳实践@reduxjs/toolkit鼓励使用最佳实践,如组织代码、分割reducers、使用异步action等。

区别

  • @reduxjs/toolkit是Redux的辅助工具集,用于简化和加速Redux开发,但它仍然是Redux的一部分。它并不是独立于Redux的状态管理库。
  • react-redux是React应用程序中与Redux集成的库,它提供了React组件和Redux store之间的连接机制,允许你将Redux store中的状态传递给React组件,以及将Redux action派发给Redux store。react-redux是与React紧密集成的,而@reduxjs/toolkit与Redux本身更相关。
  • @reduxjs/toolkit通常用于简化Redux的配置和开发过程,而react-redux用于在React应用中连接React组件与Redux store。这两者通常一起使用,但它们有不同的目的和关注点。

十五、React render方法的原理,在什么时候会触发?

在 React 中,render()方法是类组件的一个生命周期,用于定义组件的 UI 结构。它的原理是将组件的虚拟 DOM表示转化为真实的 DOM 元素,并将其插入到页面中。

当满足以下情况之一时,React 会触发组件的Render()方法:

  1. 组件初始化:在组件第一次被创建和渲染时,会调用Render()方法来生成虚拟 DOM,并将其转化为真实的 DOM 元素。
  2. 组件更新:当组件更新的状态(state)或属性(props)发生变化时,React 会根据新的状态或属性重新执行Render()方法,生成新的虚拟 DOM,并将其与之前的虚拟DOM 进行比较。如果两个虚拟 DOM 结构相同,说明组件的 UI 没有变化,此时不会触发实际的 DOM 更新。如果两个虚拟 DOM 结构不同,说明组件的 UI 发生了变化,React 会通过 Diff 算法找出差异,并仅更新改变的部分。
  3. 强制更新:有时候需要强制更新组件进行重新渲染,即使状态和属性没有变化。可以使用forceUpdate()方法来强制触发组件的Render()方法。需要注意的是,Render()方法是纯粹的,也就是说它不应该产生副作用,只关注组件的 UI 的渲染。如果要组件更新后执行一些操作,可以使用其他生命周期方法(componentDidUpdate())或钩子函数(useEffect)。

十六、Redux中同步 action 与异步 action最大的区别? 

Redux中的同步action和异步action的最大区别在于它们处理动作(actions)的方式和触发时间:

  1. 同步Action
    • 同步action是指立即执行的操作,不涉及任何异步操作。
    • 同步action的动作创建函数(action creator)会立即返回一个包含动作类型和数据的action对象,通常使用dispatch函数触发。
    • 同步action用于处理立即执行的操作,例如用户点击按钮、输入框变化等。
    • 由于同步action是立即执行的,所以它们通常用于处理简单的状态变更,不需要等待异步操作的结果。

示例:

const increment = () => ({

  type: 'INCREMENT',

});

dispatch(increment()); // 触发同步action
  1. 异步Action
    • 异步action是指涉及异步操作的动作,需要等待异步操作的结果,例如网络请求或定时任务。
    • 异步action的动作创建函数通常会返回一个函数,而不是一个包含动作对象的函数。这个返回的函数通常接受dispatchgetState作为参数,允许在异步操作完成后触发一个或多个同步action。
    • 异步action用于处理需要等待异步操作结果的情况,例如从服务器获取数据后更新应用状态。

示例:

const fetchData = () => (dispatch, getState) => {

  dispatch({ type: 'FETCH_DATA_REQUEST' });

  // 异步操作,例如发起网络请求

  api.fetchData().then(

    (data) => {

      dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });

    },

    (error) => {

      dispatch({ type: 'FETCH_DATA_FAILURE', error });

    }

  );

};

dispatch(fetchData()); // 触发异步action

总之,同步action用于立即触发状态变更,而异步action用于处理需要等待异步操作结果的情况。在Redux中,通常使用异步action来处理网络请求、定时任务等涉及异步操作的情况,以确保应用程序状态的一致性。同步action通常用于处理用户的交互操作和状态变更,它们不需要等待异步结果。

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

在React中,如果你尝试在`props.children`上使用`map`函数进行遍历,通常不会收到异常。但是,可能会出现一些问题,这取决于`props.children`的内容以及你如何处理它们。

如果你的props.children包含单个React元素或组件,map函数将无法直接使用,因为它期望一个数组来进行映射操作。如果你只有一个子元素,你可以将其包装在一个数组中,然后使用map函数遍历,如下所示:

import React from 'react';



function MyComponent(props) {

  const childrenArray = React.Children.toArray(props.children);



  return (

    <div>

      {childrenArray.map((child, index) => (

        <div key={index}>

          {child}

        </div>

      ))}

    </div>

  );

}

在上面的示例中,React.Children.toArray(props.children) 将props.children转换为一个数组,然后你可以使用map函数来遍历子元素。

另一种常见情况是props.children包含多个子元素,每个子元素都有自己的类型。在这种情况下,你可以使用React.Children.map来处理props.children,它会为你处理各种类型的子元素,如下所示:

import React from 'react';



function MyComponent(props) {

  return (

    <div>

      {React.Children.map(props.children, (child, index) => {

        return (

          <div key={index}>

            {child}

          </div>

        );

      })}

    </div>

  );

}

使用React.Children.map可以避免一些潜在的异常,因为它会处理各种类型的子元素,包括字符串、数字和React元素。如果props.children包含非React元素,直接使用map函数可能会导致异常。

需要注意的是,遍历props.children时要为每个子元素指定一个唯一的key属性,以帮助React进行有效的更新和重渲染。

十八、React 组件之间如何通信?

在React中,组件之间可以通过多种方式进行通信,这取决于组件之间的关系和需求。以下是一些常见的方法:

  1. Props传递:这是React中最基本的组件通信方式。你可以通过将数据作为props传递给子组件来实现通信。父组件可以向子组件传递数据,然后子组件可以访问这些数据并进行渲染。
  1. 回调函数:父组件可以将函数作为props传递给子组件,以便子组件可以调用这些函数来通知父组件发生了某些事件。
  1. 上下文(Context):React的上下文机制允许你在组件层次结构中的祖先组件和后代组件之间共享数据,而不必手动传递props。这对于全局状态管理非常有用。
  2. 状态管理库:对于大型应用程序,你可以使用状态管理库(如Redux、Mobx、或React的useContextuseReducer)来管理应用的状态,以便多个组件可以访问和修改共享的状态。
  3. 事件总线:你可以创建一个事件总线对象,允许组件订阅和触发事件,以便它们可以相互通信。这在某些特定情况下很有用,但要小心不要滥用它,以避免代码变得难以维护。

这些方法可以根据你的应用程序需求来选择和组合使用。通常,使用props传递数据是最常见的方式,但在某些情况下,使用上下文或状态管理库可能更合适。

十九、说说你对受控组件和非受控组件的理解?应用场景?

在React中,受控组件(Controlled Components)和非受控组件(Uncontrolled Components)是两种处理表单元素和用户输入的不同方式。

受控组件:受控组件是指组件的状态由React控制和管理。在受控组件中,组件的状态值通过props传递给组件,

并且只能通过回调函数来更新状态。

特点:状态可追踪、可控制,适用于需要对组件状态进行精确控制的场景  。

场景:例如表单输入、复杂的交互逻辑等。通过受控组件,可以实现对用户输入的验证、实时更新等操作。

非受控组件:非受控组件是指组件的状态由组件自身管理,在非受控组件中,组件的状态值不受React控制,

而是由DOM元素本身来管理

特点:简单、灵活,适用于一些简单的交互场景

场景:点击按钮、选择选项等

选择受控组件还是非受控组件取决于具体情况。一般来说,对于大多数React应用,受控组件是首选,因为它们提供了更好的数据流控制和React状态管理。然而,非受控组件可能在某些情况下更方便,尤其是当与第三方库或既有代码交互时。

总的来说,受控组件和非受控组件是React中处理表单元素和用户输入的两种不同策略,你可以根据具体需求选择合适的方法。

二十、说说javascript内存泄漏的几种情况?

JavaScript内存泄漏是指应用程序中的内存不再被使用,但没有被正确释放,导致内存占用不断增加,最终可能导致应用程序性能下降或崩溃。以下是一些常见的导致JavaScript内存泄漏的情况:

  1. 未被释放的引用:当一个对象仍然存在对其他对象的引用,即使你不再需要这个对象,它也不会被垃圾回收。这种情况通常发生在事件处理程序、闭包或全局变量中。
function leakMemory() {

  const element = document.getElementById('myElement');

  element.addEventListener('click', () => {

    // element仍然存在于内存,尽管它已不再需要

  });

}
  1. 定时器未清理:如果你创建了定时器(setTimeoutsetInterval)但没有清理它们,它们会一直运行,即使不再需要。这会导致函数和相关数据一直存在于内存中。
function createMemoryLeak() {

  setInterval(() => {

    // 未清理的定时器

  }, 1000);

}
  1. DOM引用未清理:在JavaScript中,如果你保留对DOM元素的引用,而这些元素被删除或替换,那么对这些引用的引用仍然存在于内存中,导致内存泄漏。
function createDomMemoryLeak() {

  const element = document.createElement('div');

  document.body.appendChild(element);

  // element被删除,但仍然有对它的引用

}
  1. 循环引用:循环引用是指两个或多个对象相互引用,而没有其他引用指向它们,垃圾回收器无法检测到它们不再被使用。这通常发生在对象之间的互相引用,比如父子关系或闭包。
function createCircularReference() {

  const obj1 = {};

  const obj2 = {};

  obj1.child = obj2;

  obj2.parent = obj1;

}
  1. 内存泄漏工具不足:有时,内存泄漏可能是由于工具或框架本身的问题,例如浏览器或第三方库的内存泄漏。

解决JavaScript内存泄漏的方法包括及时释放不再需要的引用、手动清理定时器和事件处理程序、避免循环引用、使用内存泄漏检测工具和定期检查和分析内存占用。

 结尾:

以上存在个人见解,如果存在错误还请各位大佬多多指教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值