目录
说一下 shouldComponentUpdate 的用途。
说一下什么是 redux、 react-redux、 redux-thunk、 redux-saga、redux-toolkit,它们之间的 区别是什么?
-
React 组件之间如何通讯?
- 父子组件传值:父组件通过props将数据或函数传递给子组件,子组件通过props传递回调函数向父组件传值。
- Redux:Redux 是一种全局状态管理库,通过 store 存储全局状态,并通过 action 和 reducer 处理状态的变化,从而实现组件之间的通信和数据共享。
- 发布订阅者模式(Event Bus):创建一个事件中心,组件可以通过订阅事件或发布事件的方式来进行通信。在 React 中,可以使用第三方库如 EventEmitter3 来实现。
- Context API:Context 提供了一种跨层级传递数据的方式,通过 Context,父组件可以将数据提供给所有子孙组件使用,子孙组件可以通过
useContext
或Consumer
获取 Context 中的数据
-
JSX 本质是什么?
jsx本质上是一种 语法拓展 ,用于在JavaScript中编写类似XML或HTML结构。 -
Context 是什么,如何应用?
Context(上下文)是一种跨组件层级传递数据的方式,避免在多层组件嵌套时通过props传递数据带来的繁琐。Context可以提供一个全局的数据源,让所有子组件都可以直接通过这个数据源获取数据。
-
使用 React.createContext(defaultValue)来创建一个Context对象。
defaultValue
是可选的默认值const MyContext = React.createContext(defaultValue);
-
在父组件中使用 MyContext.Provider 包裹子组件,通过value属性设置Context的值。
<MyContext.Provider value={contextValue}> {children} </MyContext.Provider>
-
在任一后代组件中使用 MyContext.Consumer 组件来订阅 Context 的变化来获取当前的值。
<MyContext.Consumer> {contextValue => /* 渲染使用 contextValue 的组件 */} </MyContext.Consumer>
-
或者,在函数式组件或自定义 Hook 中使用
useContext
hook 来获取当前 Context 的值。const contextValue = useContext(MyContext);
-
-
说一下 shouldComponentUpdate 的用途。
- 用于控制组件是否需要重新渲染。它的作用是在React更新渲染过程中进行性能优化,避免不必要的组件重渲染,提升应用的性能。
- 默认情况下,每当组件的状态(
state
)或属性(props
)发生变化时,React 会自动重新渲染组件及其子组件。但在某些情况下,组件并不需要更新,此时可以使用shouldComponentUpdate
来避免不必要的重渲染。
-
说一下 redux 单向数据流的机制。
- 用户在操作界面触发一个事件,例如点击按钮。
- 用户界面组件调用 Action Creator 函数创建一个 Action,并使用
store.dispatch(action)
将 Action 发送给 Store。 - Store 接收到 Action,并调用 Reducer 函数来处理 Action,生成新的状态。
- Store 中的状态更新后,会通知订阅了 Store 的 View(视图)组件。
- View 组件接收到新的状态,重新渲染界面展示最新的数据。
- 用户界面更新,等待下一次用户操作。
action > dispatch > reducer > store > view
-
React类组件的 setState 是同步还是异步操作?
-
在 React 类组件中,
setState
操作既可以是同步的,也可以是异步的,具体取决于环境和使用方式
-
异步更新(默认情况):React 通常会将
setState
视为异步操作,并对多个连续的setState
调用进行批处理。这意味着,在单个事件循环周期内,React 会将连续的setState
调用合并为一个更新来提高性能。例如,以下代码中的两个
setState
调用会被 React 合并成一个更新操作:this.setState({ count: this.state.count + 1 }); this.setState({ count: this.state.count + 1 }); // count = 1
最终的结果是
count
只会增加一次,而不是两次。React 会根据之前的状态和传递的更新函数进行计算,并在下一次渲染时应用最终的结果。 -
同步更新:有些情况下,我们需要立即获取到最新的状态。可以通过在
setState
中使用回调函数的方式实现同步更新:this.setState(prevState => ({ count: prevState.count + 1 })); this.setState(prevState => ({ count: prevState.count + 1 })); // count = 2
使用回调函数的方式可以确保每次更新都基于前一次完成后的最新状态,而不会被批处理合并。这样可以立即获得修改后的状态值。
-
-
什么是纯函数
- 是指在函数执行中,其行为仅依赖于输入参数,而不依赖于外部因素的函数。主要有两个主要特点:
-
输入决定输出: 给定相同的输入,纯函数总是返回相同的输出。纯函数在执行过程中不会改变传入的参数,也不会对外部环境造成影响。
-
没有副作用: 纯函数不会对除了函数作用域内的变量之外的其他状态产生影响。它不会修改全局变量、实例变量、读取用户输入或进行网络请求等。
-
-
由于纯函数的特性,他具有以下优势:
- 可测试性、可缓存性、可移植性和可组合性、代码可读性和可维护性。
- 是指在函数执行中,其行为仅依赖于输入参数,而不依赖于外部因素的函数。主要有两个主要特点:
-
介绍 React 组件生命周期。
-
挂载阶段:
constructor()
: 组件被创建时调用,用于初始化组件的状态和绑定事件处理方法。static getDerivedStateFromProps(props, state)
: 在组件实例化、接收到新的 props 或父组件重新渲染时调用,返回一个对象更新组件的状态(不推荐使用,推荐使用生命周期 getDerivedStateFromProps 替代)。render()
: 必选方法,根据组件的状态和传入的属性返回要渲染的内容,通常使用 JSX 语法进行描述。componentDidMount()
: 组件初次渲染后调用,可以进行 DOM 操作、数据请求等副作用操作。
-
更新阶段:
static getDerivedStateFromProps(props, state)
: 在组件接收到新的 props 或父组件重新渲染时调用,返回一个对象更新组件的状态。shouldComponentUpdate(nextProps, nextState)
: 决定组件是否需要重新渲染,默认返回 true。通过覆写此方法可以优化组件的性能。render()
: 根据新的状态和属性重新渲染组件。getSnapshotBeforeUpdate(prevProps, prevState)
: 在 render 方法之后、组件实际更新到 DOM 之前调用,用于捕获一些组件更新前的信息。componentDidUpdate(prevProps, prevState, snapshot)
: 组件更新完成后调用,可以进行 DOM 操作、数据请求等副作用操作。
-
卸载阶段:
componentWillUnmount()
: 组件即将被卸载和销毁时调用,可以进行一些清理操作,如取消计时器、清除事件监听等。
-
错误处理阶段:
static getDerivedStateFromError(error)
: 当组件内部发生错误时调用,返回一个对象更新组件状态。componentDidCatch(error, info)
: 在错误被捕获后调用,可以记录错误信息、上报错误等。
-
此外,React 16.8 版本引入了 Hooks,Hooks 可以让函数组件也具有类似生命周期的能力,例如
useEffect
可以替代componentDidMount
、componentDidUpdate
和componentWillUnmount
等方法。
-
-
React 发起 ajax 应该在哪个生命周期
- componentDidMount()
- 在组件挂载完成后的
componentDidMount
生命周期中进行,在这个时候可以保证 DOM 已经渲染完成,可以正确获取到需要发送请求的 DOM 节点信息。另外,在这个阶段发起的 AJAX 请求也不会阻塞组件的渲染过程,从而提高用户交互的响应速度
-
渲染列表,为何使用 key?
- React 会基于
key
属性来判断哪些元素被修改、删除或者添加了,从而进行高效的更新操作。
- React 会基于
-
函数组件 和 class组件的区别?
-
语法差异:函数组件是一个函数,接收 props 对象作为参数并返回 JSX 元素。而类组件则是一个继承自 React.Component 的类,通过覆写方法来定义组件的行为和渲染输出。
-
状态管理:在 React 16.8 之前,函数组件没有内置的状态管理功能,只能通过父组件传递的 props 进行数据交互。而类组件可以通过
this.state
来管理组件内部的状态,并使用this.setState()
方法来更新状态。 -
生命周期:函数组件在过去没有生命周期方法,无法直接处理组件的挂载、更新和卸载等操作。但在 React 16.8 引入的 Hooks 特性中,函数组件可以使用
useEffect()
等钩子函数来模拟类组件的生命周期行为。 -
代码复用:函数组件通常比类组件更简洁,代码量较少,易于理解和维护。它们更适合用于只展示数据的无状态组件或者具有简单交互逻辑的组件。而类组件则更适合处理复杂的组件逻辑,包括状态管理、生命周期方法、组件间通信等。
-
性能:由于函数组件的实现更简单,没有额外的实例化和维护成本,因此它们通常会比类组件具有更好的性能表现。但在大规模渲染或复杂交互场景下,类组件的性能可能略优于函数组件。
-
-
什么是受控组件、什么是非受控组件?
- 受控组件: 受控组件通过React的状态(state)来管理用户输入的表单数据。当输入框的值发生变化时,通过事件处理函数更新组件的状态,并将新的值传递给输入框。这样,输入框的值始终由React控制,在React中保持一致性并可以进行进一步的验证或处理。
- 非受控组件): 非受控组件中,表单数据被DOM自身管理。在非受控组件中,我们使用
ref
属性来访问DOM节点的实际值。
-
何时使用异步组件?
-
异步组件是一种在需要时延迟加载和渲染的组件,通常在以下情况下使用:
-
`优化初始加载性能:当应用的初始加载时间较长,或者某些组件很少被使用时,可以使用异步组件来延迟加载这些组件。这样可以减小初始加载的包大小,提高页面响应速度。
-
按需加载:在某些情况下,页面上的某些组件可能只在特定条件下需要进行加载。例如,当用户执行某个操作后需要显示一个特定的模块或弹窗时,可以使用异步组件来延迟加载这部分内容。
-
减少整体包大小:如果应用有多个页面,并且每个页面都有一些共享的大型组件,可以将这些组件拆分为异步组件,仅在需要的页面上加载,从而减小整体的包大小。
-
懒加载:当用户滚动到页面的某个特定位置或者执行某个交互操作时,可以使用异步组件来懒加载更多的内容,以提升用户体验和性能。
-
性能优化:如果你的应用有一些耗时的组件,比如图表库、数据可视化组件等,可以将它们拆分为异步组件。这样可以避免阻塞主线程,并在需要时再进行加载和渲染,提高整体性能。
-
分割代码块:当你的应用非常大或者包含多个页面时,通过使用异步组件可以将代码分割为多个小的代码块。这样可以确保只有当前页面需要的代码被加载,而其他页面的代码则可以在需要时再进行加载,减少整体包的大小。
-
-
React 提供了
React.lazy()
函数和Suspense
组件来支持异步组件的加载和渲染。
-
-
多个组件有共同逻辑,如何抽离?
- 封装公共组件,
- 自定义Hooks,
- 高阶组件HOC:创建一个接收组件作为参数并返回增强后组件的函数。通过将共同的逻辑封装在 HOC 中,多个组件可以共享这个逻辑。
-
Redux 如何进行异步请求?
- 在 Redux 中进行异步请求可以使用中间件来处理,其中最常用的中间件是 Redux Thunk 和 Redux Saga。
-
React-router 如何配置懒加载?
- 使用 React.lazy() 函数来异步加载组件,同时也可以结合使用 Suspense 组件来在组件加载完成前显示一个 loading 状态。
-
什么是 PureComponent?
- PureComponent 是 React 中的一个优化性能的组件,是 React.Component 的一个变体,在实现上自动实现了 shouldComponentUpdate 方法,自动进行浅层比较来决定是否重新进行渲染。
-
React事件 和 Dom事件有什么区别?
- 绑定方式不同
- 事件名不同
- 时间处理函数的参数不同
- 事件冒泡机制不同
- 阻止事件传播的方法不同
-
React 性能优化方式有哪些?
- 使用useCallback和useMemo
- 避免在render方法中进行重复计算
- 懒加载组件
- 分割大型组件
- 批量更新状态
- 在使用列表时,为每一个元素添加唯一的key属性
-
使用 React.memo 或 PureComponent:通过将组件包裹在 React.memo() 或使用 PureComponent,可以避免在 props 没有变化时进行不必要的重新渲染。
-
说一下 React 和 Vue 的区别。
- React是声明式的编程风格,vue是响应式的编程风格。
- vue比较简单易学,React则更加灵活
-
说一下什么是 redux、 react-redux、 redux-thunk、 redux-saga、redux-toolkit,它们之间的 区别是什么?
- Redux 是一个独立的状态管理库
- React-Redux 是与 React 集成使用 Redux 的库
- Redux-Thunk 是 Redux 的中间件,用于处理简单的异步操作
- Redux-Saga 则是用于处理复杂的异步操作的 Redux 中间件。具体使用哪个库取决于项目的需求和复杂度
- Redux-Toolkit 是 Redux 官方推出的工具集,旨在简化 Redux 应用程序的开发流程,提供了更便捷的 API 和工具。
-
- Redux:Redux 是一个独立的状态管理库,用于管理应用中的全局状态。它使用单一的状态树(state tree)来存储整个应用的状态,并通过纯粹的函数(reducer)来处理状态的变化。Redux 提供了
store
实例来存储状态,并通过dispatch
方法来触发状态变化。Redux 的核心理念是单向数据流,即状态的变化只能通过 dispatch action 来进行,然后由 reducer 响应并更新状态。 - Redux-Saga:Redux-Saga 是一个用于管理应用副作用(例如异步请求、定时器)的 Redux 中间件。它使用了 ES6 的生成器函数(generator function)来实现异步流程的控制和管理。Redux-Saga 提供了一套强大的 API 用于处理异步操作,包括监听 action、派生任务等。相对于 Redux-Thunk,Redux-Saga 可以更灵活地处理复杂的异步流程,并且可以更好地处理并发操作和取消操作。
- Redux-Thunk:Redux-Thunk 是一个 Redux 的中间件,用于处理异步操作。它允许在 Redux 中进行异步的 action 创建,即可以在 action 中返回一个函数而不仅仅是对象。这个函数可以在异步操作完成后再 dispatch 相应的 action。Redux-Thunk 的优势在于简单易用,适合处理简单的异步操作。
- React-Redux:React-Redux 是 Redux 官方推荐的用于在 React 应用中集成 Redux 的库。它提供了
connect
函数和Provider
组件,用于连接 Redux 的状态和 React 组件。通过将组件包装在connect
函数中,我们可以访问 Redux 中的状态以及将 action 和 dispatch 与组件进行绑定。Provider
组件用于在整个应用中提供 Redux 的store
。 -
Redux-Toolkit:Redux-Toolkit 是 Redux 官方推出的一个官方建议的工具集,它旨在简化 Redux 应用程序的开发流程。Redux-Toolkit 提供了一组功能强大的 API,帮助开发者更快地编写 Redux 代码并减少样板代码。其中包括了一个用于创建 Redux store 的 configureStore 函数、内置了 immer.js 用于处理不可变数据、自动为 action 创建生成唯一的字符串类型的 type 等。
- Redux:Redux 是一个独立的状态管理库,用于管理应用中的全局状态。它使用单一的状态树(state tree)来存储整个应用的状态,并通过纯粹的函数(reducer)来处理状态的变化。Redux 提供了