前端面试题大合集4----框架篇(React)

devtools/2024/10/18 16:51:07/
一、React 合成事件

Dom事件流分三个阶段:事件捕获阶段,目标阶段,事件冒泡阶段

React在事件绑定时有一套自身的机制,就是合成事件。如下比较直观:

react中事件绑定:
<div className="dome" onClick={this.handleClick}>
普通的事件绑定:
<div class="dome" onclick="handleClick()">

React合成事件机制:React并不是将click事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数运行和处理。

React合成事件原理:

  1. 当用户在为onClick添加函数时,React并没有将Click绑定到Dom上;
  2. 而是document处监听所有支持的事件,当事件发生并冒泡至document处时,React将事件内容封装交给中间层SyntheticEvent (负责所有事件合成);
  3. 然后使用统一的分发函数dispatchEvent,将封装的事件内容交由真正的处理函数执行。

React中也可以使用原生事件,合成事件和原生事件也可以混合使用:

class Demo extends React.Component {componentDidMount() {const $this = ReactDOM.findDOMNode(this)$this.addEventListener('click', this.onDOMClick, false)}onDOMClick = evt => {console.log('dom event')}onClick = evt => {console.log('react event')}render() {return (<div onClick={this.onClick}>Demo</div>)}
}

React中阻止事件冒泡调用:evt.stopPropagation()方法,由于Dom事件被阻止了,无法到达document,所以合成事件自然不会被触发。


二、React中的setState,什么时候时同步的,什么时候时异步的?

1. react18版本之前

  • setState在不同情况下可以表现为异步或同步
  1. 在Promise的状态更新、js原生事件、setTimeout、setInterval中是同步的。
  2. 在react的合成事件中,是异步的

2. react18版本之后。

  • setState都会表现为异步(即批处理)。
  1. 批处理:是指 React将多个状态更新分组到单个重新渲染中以获得更好的性能
  2. 如果同一点击事件中有两个状态更新,React 总是将它们批处理为一次重新渲染。如果运行以下代码,您将看到每次单击时,尽管您设置了两次状态,React 只执行一次渲染
function App() {const [count, setCount] = useState(0);const [flag, setFlag] = useState(false);function handleClick() {setCount(c => c + 1); // Does not re-render yetsetFlag(f => !f); // Does not re-render yet// React will only re-render once at the end (that's batching!)}return (<div><button onClick={handleClick}>Next</button><h1 style={{ color: flag ? "blue" : "black" }}>{count}</h1></div>);
}
  • 总结

setState 只在合成事件和 hook() 中是“异步”的,在 原生事件和 setTimeout 中都是同步的。

三、React Hook相关知识
1、请勿在循环或者条件语句中使用hook

因为React Hook是以单向循环链表的形式存储的,即是有序的。

循环是为了从最后一个节点移动到下一个节点的时候,只需要通过next一步就可以拿到第一个节点。

React Hook的执行,分为mountupdate阶段。在mount阶段,通过mountWorkInProgressHook()创建各个hooks(如useState、 useMemo、useEffect、useCallBack等)并且将当前hook添加到表尾。在update阶段,在获取或者更新hooks只的时候,会先获取当前hook的状态:hook.memoizedState,并且按照顺序读取或更新hook,若在条件判断或者循环中使用hooks,那么在更新阶段若增加或者减少了某个hook,hooks的数量发生变化,而React是按照顺序,通过next读取下一个hook,则导致后面的hooks和挂载阶段对应不上,发生读写错误的情况,从而引发bug。

React为什么要以单向循环链表的形式存储hooks呢?直接以key-value的对象形式存储就可以在循环或条件语句中使用hooks了,岂不更好?

这是因为react scheduler的调度策略如此,以链表的形式存储是为了可以实现并发、可打断、可恢复、可继续执行下一个fiber任务。

2、使用map循环数组渲染列表时须指定唯一且稳定的key

react中的key本质时服务于diff算法的,它的默认值是null,在diff算法中,新旧节点是否可以复用,首先就会判断key是否相同,其后才会进行其他条件的判定(如props),从而提升渲染性能,减少重复无效的渲染。

为什么在渲染列表的时候,不能讲index设置为key?

因为显式的把index设置为key,和不设置效果是一样的,这就是所谓的就地复用原则,即react在diff的时候,如果没有key,就会在老虚拟Dom树中,找到对应顺序位置的组件,然后对比组件的类型和props来决定是否需要重新渲染。

index作为key,不仅会在数组发生变化的时候,造成无效多余的渲染,还可能在组件含有非受控组件的时候,造成UI渲染错误。

如果渲染列表的时候,key重复了会怎么样?

首先react会给你输出警告,告诉你key值应该是唯一的,以便组件在更新期间保持其标识。重复的key可能导致子节点被重复使用或省略,从而引发UI bug。

3、memo

在react中,当我们setState之后,若值发生变化,则会重新render当前组件以及其子组件,在必要的时候,我们可以使用memo进行优化,来减少无效渲染。memo是一个高阶组件,接受一个组件为参数,并返回一个原组件为基础的新组件,而在memo内部,则会使用Object.is来遍历对比新旧props是否发生变化,以决定是否需要重新render。

4、useMemo和useCallback

它两个都是用来缓存数据,优化性能的。

  • 共同作用

在依赖数据发生变化的时候,才会调用传进去的回调函数去重新计算结果,起到一个缓存的作用

  • 两者的区别

useMemo  缓存的结果是回调函数中return回来的值,主要用于缓存计算结果的值,应用场景如需要计算的状态。
useCallback  缓存的结果是函数,主要用于缓存函数,应用场景如需要缓存的函数,因为函数式组件每次任何一个state发生变化,会触发整个组件更新,一些函数是没有必要更新的,此时就应该缓存起来,提高性能,减少对资源的浪费;另外还需要注意的是,useCallback应该和React.memo配套使用,缺了一个都可能导致性能不升反而下降。

5、useImperativeHandle (forwardRef)

某个组件想要暴漏一些方法,来供外部组件来调用。就需要用这个hook,需要和forwardRef来配合使用。

6、获取最新的state

在react中,setState之后,是采用异步调度、批量更新的策略,导致我们无法直接获取最新的state。

在使用class组件的时候,我们可以通过传递第二个参数,传一个回调函数来获取最新的state,但是在React18版本之后,就算在class component里面,setTimeout,原生事件回调里,也是异步批量更新了。

在hooks里面,我们目前只能通过useEffect,把当前state当作依赖传入,来在useEffect回调函数里面获取最新的state。

7、useRef

如果我们想在hooks里面获取同步最新的值,可以使用useRef;创建一个ref对象,然后挂载到hook.memoizedState,我们在修改的时候,就是直接修改ref.current。useRef其实就是提供一个稳定的变量,在组件的整个生命周期都是持续存在且是同一个引用。

注意:修改useRef返回的状态不会引起UI的重渲染。


http://www.ppmy.cn/devtools/41217.html

相关文章

在微信小程序项目中安装和使用 Vant 组件库

vant Wwapp 小程序开发组件库官网 Vant Weapp - 轻量、可靠的小程序 UI 组件库 安装 Vant 组件库 1.在微信小程序项目文件目录的空白位置右键&#xff0c;选择在外部终端窗口中打开 2在命令行输入如下命令&#xff08;在项目中创建包管理配置文件 package.json&#xff09; …

OKHTTP 3.12.0 以后版本 headers 中不可携带中文

今天遇到的报错&#xff1a; java.lang.llegalArgumentException: Unexpected char 0x957f at 0 in x-brand value: 电视堆栈 okhttp3.Headers.checkValue(Headers.java:272) okhttp3.Headers$Builder.add(Headers.java:312) okhttp3.Request$Builder.addHeader(Request.iava:…

MFC桌面应用中窗口的客户区与非客户区的

在MFC&#xff08;Microsoft Foundation Class&#xff09;中&#xff0c;窗口被分为客户区和非客户区。理解这两个概念对于设计和开发Windows应用程序至关重要。 客户区&#xff08;Client Area&#xff09;&#xff1a; 客户区是窗口中用于显示应用程序内容的区域。它是窗口…

接口自动化-requests库

requests库是用来发送请求的库&#xff0c;本篇用来讲解requests库的基本使用。 1.安装requests库 pip install requests 2.requests库底层方法的调用逻辑 &#xff08;1&#xff09;get / post / put / delete 四种方法底层调用 request方法 注意&#xff1a;data和json都…

安全 | 开源入侵防御系统 Snort

目录 Snort 概要 入侵预防系统模式 数据包记录器和嗅探器模式 网络安全学习路线 &#xff08;2024最新整理&#xff09; 学习资料的推荐 1.视频教程 2.SRC技术文档&PDF书籍 3.大厂面试题 特别声明&#xff1a; Snort 概要 Snort 概要 是世界上最重要的开源入…

Go 处理错误异常——之一

如果你习惯了 try catch 这样的语法后&#xff0c;会觉得处理错误真简单&#xff0c;然后你再来接触 Go 的错误异常&#xff0c;你会发现他好复杂啊&#xff0c;怎么到处都是 error&#xff0c;到处都需要处理 error。 首先咱们需要知道 Go 语言里面有个约定&#xff0c;就是一…

AI图像生成-原理

一、图像生成流程总结 【AI绘画】深入理解Stable Diffusion&#xff01;站内首个深入教程&#xff0c;30分钟从原理到模型训练 买不到的课程_哔哩哔哩_bilibili 二、如果只是用comfy UI生成图片 1、找到下面几个文件&#xff0c;把对应模型移动到对应文件夹即可使用 2、选择对…

《Python深度学习,第3版》

书籍&#xff1a;Python Deep Learning&#xff1a;Understand how deep neural networks work and apply them to real-world tasks&#xff0c;Third Edition 作者&#xff1a;Ivan Vasilev 出版&#xff1a;Packt Publishing 书籍下载-《Python深度学习&#xff0c;第3版…