目录
1、setState是异步还是同步
setState可以是同步的,也可以是异步的,当setState在React事件处理程序中调用时,他通常是异步的。他会将一系列的setState调用合并为单个更新,在这种情况下,React将在未来的没有一个时间点进行更新,而不是立即更新组件状态,这意味着React可以批量处理多个setState调用并一次性更新组件状态,以提高性能。当setState被放到立即执行函数中,React是不会进行批量更新的,而是立即更新组件状态,这种情况下,就是同步的。
2、React合成事件是什么,与原生事件的区别是什么?
点React合成事件是React框架自己实现的一套事件处理机制,这个机制在底层使用了浏览器原生的事件机制,但对事件做了进一步的封装和优化。React合成事件具有以下特点:
- 事件委托:React将事件绑定在父组件节点上,通过事件冒泡的机制来处理子组件的事件。这种方式可以减少事件绑定的数量,提高性能。
- 自动绑定this:React会自动将事件处理函数绑定到组件实例对象上,省去了手动绑定this的步骤。
- 跨浏览器兼容:React合成事件在不同浏览器上表现一致,而原生事件受浏览器差异的影响较大。
- 对事件对象的封装:React对原生事件对象进行封装,提供了一些额外的属性和方法。
与原生事件相比,React合成事件的处理过程是异步的。React会将所有的事件处理函数放入一个事件队列中,等到合适的时刻再批量执行。这种机制可以提高性能,避免频繁更新DOM。但也意味着,如果事件处理函数中有对状态的修改,事件处理函数执行时可能会拿到旧的状态值,而不是最新的状态值。因此,React提供了一些钩子函数(如componentDidUpdate)来处理这种情况。
3、什么是虚拟DOM?VirtualDOM及其工作原理
Virtual DOM 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本。它是一个节点树,它将元素、它们的属性和内容作为对象及其属性。 React 的渲染函数从 React 组件中创建一个节点树。然后它响应数据模型中的变化来更新该树,该变化是由用户或系统完成的各种动作引起的。
Virtual DOM 工作过程有三个简单的步骤。
- 每当底层数据发生改变时,整个 UI 都将在 Virtual DOM 描述中重新渲染。
- 然后计算之前 DOM 表示与新表示的之间的差异。
- 完成计算后,将只用实际更改的内容更新 real DOM。
4、类组件和函数组件之间的区别是啥?
在React中有两种组件形式:类组件和函数组件。类组件是使用ES6类语法定义的组件,而函数组件是使用函数定义的组件,它们之间的主要区别如下:
- 语法:类组件使用 ES6 的类语法定义,而函数组件则使用函数语法定义。
- 状态管理:类组件可以使用状态(state),而函数组件原先无法使用状态,但是现在可以使用 React Hooks 来实现状态管理。
- 生命周期:类组件有完整的生命周期函数,函数组件可以使用 useEffect 来替代生命周期函数的部分功能。
- 性能:在一些情况下,函数组件的性能比类组件更好。
总体来说,如果需要使用状态或生命周期函数,或者需要更灵活的组件管理方法,应该使用类组件,否则可以使用函数组件。但是根据具体的业务场景和个人习惯,这个选择会有所不同。
5、React 中 refs 干嘛用的?
Refs 是 React 提供的一种访问 DOM 元素或组件实例的方式。通过在 JSX 元素上添加 ref 属性并设置其值为一个回调函数,可以在组件挂载后或更新后访问到对应的 DOM 元素或组件实例。
Refs 的常见用途包括:
- 控制焦点,比如在某个组件挂载后自动聚焦到某个输入框上。
- 操作 DOM,比如在某个按钮被点击时修改 DOM 的样式或属性。
- 访问组件实例,比如在某个组件中调用其公共方法获取数据或执行某些操作。
需要注意的是,Refs 应该尽量避免在业务逻辑中过多地使用,因为它会增加组件之间的耦合性,降低代码的可维护性。在 React 中,推荐使用 props 和 state 来进行组件之间的数据传递和交互。只在必要的时候使用 Refs。
6、state 和 props 区别是啥?
在 React 中,state 和 props 都是用来存储组件的数据的,它们的主要区别在于:
- 定义位置不同:props 是组件的属性,它由父组件传递给子组件,子组件不可以直接修改它的值;而 state 是组件的状态,它是组件内部自己管理的,可以通过 setState 改变它的值。
- 是否可变:props 是只读的,子组件不能直接修改父组件传递下来的 props;而 state 是可变的,组件可以通过 setState 方法修改它的值。
- 触发时机不同:props 是在组件挂载时由父组件传递下来的,它只会在父组件重新渲染时才会更新;而 state 是在组件内部管理的,任何时候都可以通过 setState 方法更新它的值。
总的来说,props 用于组件之间的数据传递和交互,一般由上级组件向下级组件传递;而 state 则是组件的内部状态,用于控制组件的行为和渲染结果。在编写组件时,应该尽可能地使 props 和 state 简单化,避免过多地使用嵌套结构,以提高组件的可维护性和复用性。
7、如何创建 refs 与使用场景
Refs 是 React 中一种访问 DOM 元素或组件实例的方式。Refs 是通过使用 ref 属性在 React 元素上创建的,并可以在组件中通过 this.refs 属性进行访问。
创建 Refs:
- 字符串 Refs:在 React 元素上添加 ref 属性,并为其指定一个字符串值。
class MyComponent extends React.Component {
handleClick() {
this.refs.myInput.focus();
}
render() {
return (
<div>
<input type="text" ref="myInput" />
<button onClick={this.handleClick.bind(this)}>Focus Input</button>
</div>
);
}
}
- 回调 Refs:在 React 元素上添加 ref 属性,并为其指定一个回调函数。
class MyComponent extends React.Component {
handleClick() {
this.myInput.focus();
}
render() {
return (
<div>
<input type="text" ref={(input) => { this.myInput = input; }} />
<button onClick={this.handleClick.bind(this)}>Focus Input</button>
</div>
);
}
}
使用场景:
- 获取 DOM 元素的值或属性。
- 给 DOM 元素设置样式。
- 控制第三方库中的 DOM 元素。
- 获取组件实例以调用其方法或访问其状态。
8、函数组件与类组件生命周期
函数组件和类组件都有生命周期,但是两者的生命周期函数不完全相同。在React 16.8之前,函数组件没有生命周期函数,但是通过React Hooks,函数组件也可以使用生命周期函数。
以下是函数组件和类组件的相应生命周期函数:
函数组件:
- useState: 获取或设置当前组件的状态
- useEffect: 在组件渲染完成后执行副作用操作,如请求数据、修改DOM、注册事件等
- useContext:用于获取全局上下文
- useReducer: 替代useState,更适用于复杂逻辑状态的处理
- useCallback: 防止函数重复渲染,提升组件性能
- useMemo: 优化组件性能,缓存函数返回值
- useRef: 获取虚拟DOM或者DOM元素的引用
类组件:
- constructor:组件创建时调用,用于初始化状态和绑定事件
- static getDerivedStateFromProps:在组件渲染前调用,将props映射到组件状态中去
- shouldComponentUpdate:用于优化组件性能,控制组件是否需要重新渲染
- render:负责输出组件的虚拟DOM
- componentDidMount: 组件挂载完成后调用,可以进行DOM操作和数据请求等副作用操作
- componentDidUpdate: 组件更新后调用,用于进行副作用操作
- componentWillUnmount: 组件卸载前调用,用于清除组件状态、事件等资源。
9、受控组件和非受控组件区别是啥?
在React中,受控组件和非受控组件是两种用于管理表单输入的不同方式。
受控组件是由React管理其状态的表单组件,其值被React的状态(state)所控制。在受控组件中,每次输入时都会更新React的状态,并且React会重新渲染组件以反映该状态的变化。通过这种方式,React可以轻松地监控和处理表单的输入。一些常见的受控组件包括input、textarea、select等。
非受控组件则相反,其值由DOM自身的状态所控制。在非受控组件中,React只是渲染静态的表单,不会监控表单的输入,因此无法处理和验证表单的输入。如果需要获取表单输入,需要直接访问DOM节点来获取表单的值。一些常见的非受控组件包括原生的input、textarea、select等。
总体来说,受控组件提供了更高级和更可控的表单输入机制,但也需要更多的代码来实现。非受控组件则更简单直接,但也更难以管理和控制表单输入。因此,选择哪种方式取决于具体的需求和项目情况。
10、什么是 React.createElement?
React.createElement是React用于创建React元素(React element)的函数。React元素是React中最基本的构建块,是描述UI界面的对象,它们不是DOM元素,而是虚拟DOM(virtual DOM)。在使用React开发应用时,我们使用React.createElement函数来构建React元素,再通过React DOM库将其渲染为真实的DOM节点。
11、讲讲什么是 JSX?
JSX是一种JavaScript的扩展语法,用于在React中编写声明式UI组件。它被设计成类似于HTML的语法,但实际上它是JavaScript表达式的语法糖。
通过使用JSX,可以直接在JavaScript代码中编写HTML标签和元素,它同时也支持自定义元素和组件。它还可以在JSX语法中嵌入JavaScript表达式,实现动态的UI渲染。在React中,JSX被视为React元素的一种表现形式,它最终被编译成普通的JavaScript函数调用。
12、为什么不直接更新 state 呢 ?
在React中,我们应该始终遵循单向数据流的原则,即数据只能从父组件向子组件传递,子组件不能直接修改父组件的数据。这是因为当子组件可以直接修改父组件的数据时,我们就无法判断组件状态的来源,这会导致代码的可维护性和可靠性降低。
同样的道理,组件状态应该由它自己来管理和更新。当状态发生变化时,React会重新渲染组件以反映这些变化。但是,React并不保证状态变化是同步和即时发生的,因此我们不能直接依赖状态的当前值来计算新值。
为了解决这个问题,React提供了一种称为setState的方法来修改组件状态。这个方法接受一个新状态对象,并安排在未来更新组件状态。通常情况下,React会尽快更新组件状态以反映应用程序的最新状态。
因此,我们应该始终使用setState来更新组件状态,而不是直接修改它。这种做法不仅符合React的单向数据流原则,还可以保证React能够正确地跟踪组件状态的变化,并及时反映应用程序的最新状态。
13、使用 React Hooks 好处是啥?
使用 React Hooks 有以下好处:
- 更少的样板代码:React Hooks 可以减少大量的样板代码,使代码更加简洁。
- 更好的可复用性:使用 hooks 可以更好地抽象和重用组件逻辑。
- 更好的测试性:Hooks 让我们可以更容易地编写测试,并更容易创建独立的组件。
- 更好的性能:Hooks 可以减少组件渲染时的重复计算和重复渲染,从而提高性能。
- 更好的代码组织:使用 Hooks 可以将相关的逻辑放在一起,更好地组织代码,减少耦合性。
14、React 中的 useState() 是什么?
useState() 是 React 中一个 Hook 函数,用于在函数组件中添加状态。它接收一个初始值作为参数,并返回一个状态值和一个更新状态的函数。通过调用更新状态的函数,可以在组件中更新该状态的值。使用 useState() 可以让函数组件变得更加灵活和可维护,使得组件状态的管理更加简单易懂。