-
受控组件和非受控组件
- 受控组件:可以通过 value 来进行双向数据绑定,例如 input 、textarea 等
- 非受控组件:不能进行双向数据绑定,例如 div 、span 等
-
React 生命周期函数
- 挂载:construct、render、componentDidMount
- 渲染:render、componentDidUpdate
- 卸载:componentWillUnMount
-
什么是高阶组件
一个组件作为参数传入另一个组件中,返回一个新的组件,这个新的组件拥有这两个组件的功能和优点。例如 withRoute
-
为什么会出现 hooks
- 类组件代码量大,每次渲染都要实例化,占用内存,难以维护。项目中大量使用类组件容易造成内存泄漏和性能消耗问题。
- 类组件通常是单例模式,复用性不高,也很难进行单元测试,难以测试。且类组件的状态管理很复杂,难以调试,容易导致错误和性能问题。
- 类组件的数据和函数距离过远,不利于逻辑并和,对标 VUE2 和 VUE3 关系
-
React 事件和普通 HTML 事件不同
- React 是合成事件,做一个兼容性处理,能够性能优化。
- 原生使用 addEventListener 监听的,React 使用 onChange 监听。
- React 必须使用特定的 API 来更新组件状态。例如,使用 setState 方法更新组件状态时,必须使用 componentDidUpdate 作为回调函数。
- 考虑组件的状态和 props,以确保正确的行为和数据绑定。例如,如果一个事件处理程序修改了组件的状态,那么它必须通过 useEffect 钩子来确保状态更新被正确地反映在组件上。
- React 事件处理程序必须考虑异步操作和副作用。例如,如果一个事件处理程序执行了一个异步操作并返回一个 Promise,那么它必须使用 useEffect 钩子来确保该 Promise 在组件卸载时被正确地处理。
-
什么是合成事件
合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象,其优点如下:
- 兼容所有浏览器,更好的跨平台;
- 将事件统一存放在一个数组,避免频繁的新增与删除 (垃圾回收)
- 方便 react 统一管理和事务机制
-
React 高阶组件、renderprops、hooks的区别
- 高阶组件 HOC、renderprops 和 hooks 都是用来扩展 React 组件功能的工具。
- 高阶组件接收一个组件作为参数,并返回一个新的组件。常用于实现权限控制、路由跳转等功能。
- renderprops 是将 props 作为函数的参数传递给组件,在组件内部调用 props 来动态渲染子元素。
- hooks 是 16.8 新增的一个 API。renderprops、hooks 常用于实现动态渲染、数据绑定等功能,且只适用于函数式组件
-
React Fiber
- React Fiber 是一种轻量级的、可变的数据结构,每个 Fiber 对象都有一个唯一的 ID和一些状态信息,如优先级、挂起时间等。
- Fiber 的主要作用是将 React 的渲染任务划分为更小、更细粒度的部分,从而提高渲染效率,更好地管理内存和资源
- Fiber 能够并行执行多个渲染任务,充分利用多核处理器的优势
- Fiber 的引入对 React 的性能提升非常明显。使用了 Fiber 的 React 可以更好地处理大量的渲染任务,并在不同的组件之间高效地切换,还能减少阻塞和卡顿的情况。同时,Fiber 还可以帮助开发者更好地管理内存和资源,从而避免了一些常见的性能问题。
-
哪些方法会让 React 重新渲染
- 组件的状态发生变化,例如 props、state、context、refs等
- 类组件的 this.setState 或者函数组件 useState 中的 setList
- 组件的父组件或者祖先组件的状态或属性发生了变化,导致子组件需要重新渲染
- 组件卸载的时候调用 componentWillUnMount 也会重新渲染
- 组件的 shouldComponentUpdate 方法返回值为 true 时也会重新渲染
- 组件的 key 属性发生了变化,导致 React 需要重新计算子树结构并进行重新渲染。
-
React 的 render 函数做了什么
- render 函数是组件渲染的核心方法,它的作用是将组件的状态和属性转化为虚拟 DOM 转换成 HTML 元素,并将其渲染到页面上。具体来说,render 函数做了以下几件事情:
- 获取组件的 props 和 state
- 根据 props 和 state 的值,进行一些必要的处理,例如计算属性、修改状态等。
- 根据组件的结构和样式,生成一个 UI 。
- 需要的话,可以通过 render 向页面添加事件监听器,便于用户交互或其他事件发生时执行相应的操作。
-
React 如何判断什么时候重新渲染组件
- 手动写一个 shouldComponentUpdate
- useEffect
- 使用 pure.component
-
声明组件的几种方式
- function
- class 类名 extends React.component
- 箭头函数
- 高阶组件
- ES5 中的 React.createClass 来创建类组件
-
有状态组件和无状态组件
- 16.8之前,函数组件被称为无状态组件,因为它无法实现响应式数据,没有生命周期等,16.8之后,函数组件有了 hooks,可以实现响应式数据
- 类组件也叫有状态组件,因为它可以实现响应式数据,有生命周期
有状态组件使用场景:
- 需要在组件内部保存一些数据的场景,例如表单组件、评论组件等;
- 需要在组件内部处理一些复杂的逻辑的场景,例如图表组件、表格组件等;
- 需要在多个子组件之间共享数据的场景,例如路由组件、应用程序入口组件等。
无状态组件使用场景:
- 只要求展示数据的场景,例如图标、按钮、标签等;
- 需要在多个组件之间共享数据的场景,例如导航栏、页脚等;
- 需要复用相同结构的组件的场景,例如列表、表格等。
-
Fragment 的理解
Fragment 是 React 中一种特殊的组件,将多个子组件组合成一个单独的节点,可以避免重复渲染和不必要的性能开销。对标 Vue2 中的 templete
-
Portals 的理解
- Portals 通过创建一个“传送门”来传送 UI。具体来说,Portals 允许将子组件的内容“传送”到父组件中,并且可以实现父子组件之间的通信。对标 Vue3 中的 teleport
-
说下你都是用过哪些React Hooks ?
1、React 自带的 hooks:
- useState:设置响应式数据。
- useEffect:副作用钩子,用于订阅事件、发送网络请求等。它是异步的会执行多次,执行时机是渲染之后,所以容易出现页面闪动现象
- useLayoutEffect:同步的只会进行一次渲染,执行时机是渲染之前,常用于解决页面闪动问题,可以性能优化
- useContext:访问上下文,共享数据。
- useReducer:管理复杂的状态逻辑。
- useRef:获取DOM元素。
- useMemo:计算属性。
- useId:返回一个id。
- useCallback:用于缓存一个回调函数。
- useTransition:异步渲染页面,可以性能优化
2、插件带的 hooks:
- useLocation:获取路由的路径、参数等信息
- useHistory:获取路由导航相关方法,如“push”、“replace”等
- useNavigate:用于路由跳转。
- useParams:获取组件的参数
- Portals:相当于 vue3 的传送门
- useDispatch:获取 dispatch 函数,用于触发 Redux 的动作
- useSelector:从 Redux store 中选择并访问状态数据。
- useAppSelector:负责将数据绑定全局数据。
- useAppDispatch:将数据传给全局处理函数,他调用会返回一个 dispatch 函数,这个函数可以调用 reducer 函数。
3、自定义 hooks:
- useMousePosition(获取鼠标移动的坐标)
- usePagination(用于分页)
- useLocalStorage(本地存储)
-
类组件中绑定 this 的方式有哪些?
- 使用 bind
- 使用箭头函数,它的 this 指向上下文
- 在构造函数中,使用 bind
class A extends React.Component{ construct(props){ super(props) this.state={ num:11 } } this.addnum = this.addnum.bind(this) } addnum =()=>{ this.state.num+1 }
-
说下对 Redux 的理解
- Redux 是一个强大的状态管理工具,它能更好地组织和管理应用程序的状态。
- React Component 需要获取一些数据, 然后它就告知 Store 需要获取数据,Store 接收到之后去 Reducer 查一下,Reducer 会告诉 Store 应该给这个组件什么数据
-
说下对 MobX 的理解
看主页 MobX 的使用讲解
-
说下对 RTK 的理解
看主页 RTK 的使用讲解
-
Redux、MobX 、ReduxToolkit 区别
它们都是状态管理库,下面是它们之间的一些区别:
- Redux 和 ReduxToolkit 的 API 设计比较相似,都是基于 ES6 的类和方法来实现的。而 MobX 则采用了更简单的函数式 API,使得开发者可以更加方便地使用。
- ReduxToolkit 在性能方面进行了一些优化,例如支持异步操作、自动生成 connect 函数等,从而可以提高应用程序的性能和响应速度。而 Redux 和 MobX 在性能方面的表现相对较为平均。
- ReduxToolkit 在功能扩展方面比 Redux 和 MobX 更丰富,例如支持多个 Store、提供高阶组件等。而 Redux 和 MobX 则相对简单,只提供了基本的功能。
-
setState 是同步还是异步的,调用后做了什么?如何实现同步?
- setState 是异步的。当调用 setState() 方法时,React 会将更新后的 state 放入一个队列中,并在下一次渲染时执行,这里注意它不会立即执行,需要立即执行某些操作的话,使用 componentDidUpdate()方法。
- 实现同步:使用一个回调函数,这个回调函数是更新完后执行
this.setState({ num:12 },()=>{ console.log(num) })
-
Vue 和 React 的区别
- Vue 是一个渐进式的框架,React 是一个轻量级的库。
- Vue 采用的是组件式开发,将 HTML+JS+CSS 写在一起,React 使用的是 JSX 的语法。
- Vue 采用 MVVM 框架,React 是单向数据流。
- Vue 不兼容 IE8 ,React 兼容 IE8。
- Vue 开发速度快,代码量小,自带全家桶不够灵活,React 第三方生态繁荣,较为灵活但是代码量大。
-
React 中常见的组件通信方式
- 父子组件传值:父组件准备一个 state 数据,子组件使用 props / this.props 接收
- 子父组件传值:父组件准备一个回调函数,子组件使用 props / this.props 接收回调函数传参,父组件接收参数
- 兄弟组件传值:使用一个父组件作为中间件通信,父组件准备一个回调函数,哥组件使用 props / this.props 接收回调函数传参给父组件,弟组件又通过 props / this.props 接收父组件中的数据
- 跨组件传值:使用 provider 和 comsumer
- 可以使用状态管理工具,例如 Redux、MobX 等
- 钩子函数 useContext 共享数据
- 使用 localStorage 等存储方式
- router 路由也可以进行一些传值
-
useEffect 和 useLayoutEffect 的区别
- useEffect :它会在组件渲染后执行,异步的。
- useLayoutEffect:它会在组件渲染前执行,最终真实的DOM只渲染一次,同步的。
-
用 TS 结合 React 项目说下使用场景
- 函数组件 FC:可以判断很多 JSX 语法错误
- 函数组件 props 传值限制
- RTK 的 TS 限制类型
- axios 封装时,接口设计
-
React 的设计思路和理念
- 组件化开发:React 将整个应用程序看作是由多个组件组成的,每个组件都有自己的状态和行为。这种组件化的开发方式使得代码更加模块化、可重用、易于维护和扩展。
- 虚拟 DOM:React 通过使用虚拟 DOM 来提高渲染性能。
- JSX 语法:React 使用 JSX 来描述 UI 元素。
- 单向数据流:React 采用单向数据流的设计思想,即从父组件到子组件的数据传递只能是单向的。这种设计方式使得应用程序的状态管理更加简单、清晰和可控。
-
React 如何实现 v-show
- 组件上使用的是父子组件传值,父组件传递一个 ‘v-show’ ,子组件使用 props 接收 ‘v-show’,内部传递一个 boolean 值,来控制 display 的属性是 none 还是 block
- 元素上直接使用 style 属性
-
React 的遍历方法
- 常使用 map、forEach
-
为什么 useState 使用数组而不是对象
- 数组是可变的,可以在运行时修改其内容,而对象则不是。如果将状态设置为对象,当状态发生变化时,需要重新渲染整个组件,这会影响性能。
- 数组可以通过索引来访问其元素,这样可以方便地获取或修改数组中的特定元素。而对象则需要通过键来访问其元素,这会增加代码的复杂度。
- 在早期版本的 React 中,只有数组支持浅拷贝,这意味着当我们将状态从父组件传递给子组件时,只有数组会被浅拷贝到子组件的状态中。而对象浅拷贝会导致状态不同步的问题。
-
React-Router 中的 Link 和 a 标签的区别
- Link 可以实现传参,它通过 to 来跳转到对应路径,a 通过 href 来跳转不能传值
- Link 跳转不会进行页面刷新,a 会有默认刷新效果
- Link 可以实现重定向、历史记录等,a 标签只能用于普通的跳转
- Link 可以说是 a 标签的一个封装,主要做了一下三步:1、定义 onClick 方法,执行该 onClick 方法;2、点击时阻止 a 标签默认行为;3、再取得跳转 href ,此时只是链接变了,并没有刷新页面
-
如何解决 props 嵌套过深的问题
使用其他传值方式,例如 Redux、MobX 等或者使用 useContext 钩子函数