1.jsx转化过程
React.createElement(…) ,Babel帮助我们完成了这个转换的过程,取defaultProps对默认props进行赋值,构造成一个虚拟DOM对象,ReactDOM.render将生成好的虚拟DOM渲染到指定容器上
2.fiber架构的理解,解决了什么问题?
JavaScript引擎和页面渲染引擎两个线程是互斥的,当其中一个线程执行时,另一个线程只能挂起等待
Fiber为每个任务增加了优先级,优先级高的任务可以中断低优先级的任务
增加了异步任务,调用requestIdleCallback api,浏览器空闲的时候执行
dom diff树变成了链表,一个dom对应两个fiber(一个链表),对应两个队列,为了找到被中断的任务,重新执行
3.说说对React Hooks的理解?解决了什么问题?
useState
useEffect
useReducer
useCallback
useMemo
useRef
4.说说对高阶组件的理解?
接受一个或多个函数作为输入,输出一个函数
const EnhancedComponent = highOrderComponent(WrappedComponent);
5.说说对受控组件和非受控组件的理解?应用场景?
受控组件是指其值由组件本身的state(或props)进行控制和管理的组件,组件的值存储在state(或props)中,并通过事件处理函数来更新。
受控组件的应用场景:输入框、复选框、下拉菜单等组件时,可以利用受控组件的特性来实现实时输入验证、数据收集等功能
多个组件之间需要共享和同步状态的场景、需要对用户输入进行实时处理和验证的场景。
非受控组件是指其值由DOM本身进行管理的组件,通过ref来获取其值
6.React中组件之间如何通信?
父组件向子组件传递:只需在子组件标签内传递参数
function EmailInput(props) {
return (
);
}
const element =
子组件向父组件传递:父组件向子组件传一个函数,然后通过这个函数的回调,拿到子组件传过来的值
兄弟组件之间的通信:父组件作为中间层来实现数据的互通
父组件向后代组件传递:React.createContext创建一个context、Provider组件用于创建数据源,Consumer组件用于接收数据
7.说说React的事件机制?
先执行原生事件,然后处理 React 事件,最后真正执行 document 上挂载的事件
8.说说 Real DOM 和 Virtual DOM 的区别?优缺点?
Real DOM是指浏览器中实际存在的DOM树,它是由HTML文档解析而来的,包含了网页中所有的元素和其属性,小规模的DOM变动,Real DOM可以及时更新,保证显示的准确性
Virtual DOM是在内存中构建的一层抽象,它是Real DOM的轻量级副本
Real DOM适合于小规模的DOM变动,并可以直接操作DOM进行增删改查。而Virtual DOM通过优化更新操作,提高了性能和灵活性,尤其适用于大规模或频繁的DOM变动场景
9.React 和 Vue 在技术层面有哪些区别?
组件化方式不同、数据驱动方式不同、模板语法不同、生命周期不同、状态管理方式不同、性能优化方式不同
10.useRef / ref / forwardsRef 的区别是什么?
都是 React 中用于操作 DOM 元素或自定义组件实例的工具
useRef 是一个 hook 函数,可以在函数组件中使用;ref 是一个对象属性,只能在类组件中使用
useRef 返回一个可变的 ref 对象,可以在组件的整个生命周期内保持不变,也就是说不会因为重新渲染而改变。而 ref 每次渲染都会被重新创建。
forwardRef 是用于将 ref 属性“向下传递”给一个函数式子组件或自定义组件的工具函数。它允许父组件调用子组件中的 DOM 元素或自定义组件实例
11.使用 React hooks 怎么实现类里面的所有生命周期?
useState 只在初始化时执行一次,后面不再执行;
useEffect 第二个参数是一个数组,如果数组为空时,则只执行一次(相当于componentDidMount);如果数组中有值时,则该值更新时,useEffect 中的函数才会执行;如果没有第二个参数,则每次render时,useEffect 中的函数都会执行;
12.React.memo() 和 useMemo() 的用法是什么,有哪些区别?
React.memo() 是一个高阶组件 (HOC),它接收一个组件A作为参数并返回一个组件B,如果组件B的 props(或其中的值)没有改变,则组件 B 会阻止组件 A 重新渲染 。
useMemo() 是一个 React Hook,我们可以使用它在组件中包装函数。 我们可以使用它来确保该函数中的值仅在其依赖项之一发生变化时才重新计算
13.setState 是同步,还是异步的?
setState在不同情况下可以表现为异步或同步
Promise的状态更新、js原生事件、setTimeout、setInterval…中是同步的
react的合成事件中,是异步的
react18之后,setState都会表现为异步(即批处理)
14.为什么不能在循环、条件或嵌套函数中调用 Hooks?
Hooks 只能在 React 函数组件的顶层调用,确保在每次渲染中 Hooks 的调用顺序一致。这样可以保证组件状态的稳定性,有效避免错误的行为和难以排查的问题。
React 依赖于 Hooks 的调用顺序和数量来确定每个组件实例的状态,循环、条件或嵌套函数会破坏 Hook 调用顺序
15.useEffect 与 useLayoutEffect 有什么区别?
useEffect 在 React 的渲染过程中是被异步调用的,用于绝大多数场景;而 useLayoutEffect 会在所有的 DOM 变更之后同步调用
useEffect是按照顺序执行代码的,改变屏幕像素之后执行(先渲染,后改变DOM),当改变屏幕内容时可能会产生闪烁;useLayoutEffect是改变屏幕像素之前就执行了(会推迟页面显示的事件,先改变DOM后渲染),不会产生闪烁
useLayoutEffect总是比useEffect先执行
16.为什么 useState 返回的是数组而不是对象?
在自定义 hook 的时候可以遵循一个简单原则:当参数大于 2 个的时候返回值的类型返回 object, 否则返回数组。
17.react中懒加载的实现原理是什么?
// 不使用 React.lazy
import OtherComponent from './OtherComponent';
// 使用 React.lazy
const OtherComponent = React.lazy(() => import('./OtherComponent'))
18.为什么不能用数组下标来作为react组件中的key?
react 使用diff算法,使用key来做同级比对。如果使用数组下标作为key
数组头部或中部插入或删除元素: 所有key对应的节点的值发生更改,进行重新渲染
如果使用数组中唯一值来作为key:不管是在何处插入或删除节点,其他key对应的节点的值未发生更改,只需插入或删除操作的数组节点。
19.React有哪些性能优化的方法?
使用生产环境构建、虚拟化长列表、使用 memoization 避免不必要渲染 缓存计算结果、懒加载组件,将应用拆分成多个异步加载的代码块,懒加载那些在初始渲染时不需要的组件、React DevTools 进行性能分析、 webpack 或其他打包工具进行代码分割
20.使用React Hooks有什么优势?
更简洁的代码、更好的复用逻辑、更方便地处理状态、更灵活的副作用处理、更好的性能优化、更好的 TypeScript 支持
21.为什么不能直接使用 this.state 改变数据?
因为并不会重新触发render
评论区