第1题:constructor中super与props参数一起使用的目的是什么?
在 React 类组件的构造函数中,我们通常会看到 super(props)
这样的代码。
super(props)
的目的是调用父类(即 React.Component)的构造函数,并将 props 参数传递给父类的构造函数。这是为了确保在子类的构造函数中能够正确地初始化父类的属性和方法。
在 React 组件中,我们通常会在构造函数中初始化组件的状态(state),绑定事件处理方法,或者进行其他一些初始化操作。而在构造函数中调用 super(props)
,可以让我们在构造函数中访问 this.props
,以便在组件的构造阶段就能够使用传递给组件的属性。
另外,如果在构造函数中需要访问 this.props
,但没有调用 super(props)
,那么在构造函数中访问 this.props
会返回 undefined。这是因为在调用 super()
之前,子类的构造函数还没有执行,所以 this.props
还没有被初始化。
总结来说,super(props)
的目的是确保在子类的构造函数中能够正确地初始化父类的属性和方法,并在构造函数中访问 this.props
。
代码说明:
class ParentComponent extends React.Component {
constructor(props) {
super(props);
console.log(props);
}
}
class ChildComponent1 extends ParentComponent {
constructor(props) {
super(props); // 调用父类构造函数,并传递props
console.log(this.props); // 输出:{ name: 'John' }
}
}
class ChildComponent2 extends ParentComponent {
constructor() {
super(); // 调用父类构造函数,没有传递props
console.log(this.props); // 输出:undefined
}
}
// 使用 ChildComponent1 和 ChildComponent2
const child1 = new ChildComponent1({ name: 'John' }); // 输出:{ name: 'John' }
const child2 = new ChildComponent2(); // 输出:undefined
第2题:什么是受控组件?
受控组件是指由 React 组件管理其内部状态的表单元素。这意味着表单元素的值由组件的 state 控制,并通过回调函数来更新状态。当用户与受控组件交互时,组件会更新其状态,并在需要时将新的值传递给表单元素。
通过受控组件,你可以实时获取和更新表单元素的值,并在组件的 state 中进行处理。这使得对表单数据进行验证、处理和提交变得更加灵活和可控。
另一方面,非受控组件则是由 DOM 自己管理其值的表单元素。在非受控组件中,你需要使用 ref 来获取表单元素的值,并手动处理用户输入的数据。非受控组件适用于一些简单的场景,但在复杂的表单处理中,受控组件通常更易于管理和维护。
非受控组件,即组件的状态不受React控制的组件,例如:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Demo1 extends Component {
render() {
return (
<input />
)
}
}
ReactDOM.render(<Demo1/>, document.getElementById('content'))
在这个最简单的输入框组件里,我们并没有干涉input中的value展示,即用户输入的内容都会展示在上面。如果我们通过props给组件设置一个初始默认值,defaultValue属性是React内部实现的一个属性,目的类似于input的placeholder属性。
受控组件:
受控组件就是组件的状态受React控制。上面提到过,既然通过设置input的value属性, 无法改变输入框值,那么我们把它和state结合在一起,再绑定onChange事件,实时更新value值就行了。
class Demo1 extends Component {
constructor(props) {
super(props);
this.state = {
value: props.value
}
}
handleChange(e) {
this.setState({
value: e.target.value
})
}
render() {
return (
<input value={this.state.value} onChange={e => this.handleChange(e)}/>
)
}
}
第3题:什么是JSX?
JSX 是 JavaScript 的语法扩展,用于在 React 中描述用户界面的结构和外观。它类似于模板语言,但实际上是 JavaScript 代码,可以在其中嵌入 JavaScript 表达式。
使用 JSX,你可以在 JavaScript 中编写类似 HTML 的代码,以声明式地描述 UI。它将 HTML 标记和 React 组件结合在一起,使得构建 UI 变得更加直观和可读。
例如,下面是一个使用 JSX 的 React 组件的例子:
import React from 'react';
class MyComponent extends React.Component {
render() {
return (
<div>
<h1>Hello, World!</h1>
<p>This is a JSX example.</p>
</div>
);
}
}
在 JSX 中,你可以使用 HTML 标签、组件和 JavaScript 表达式。你可以在标签中使用属性来传递数据给组件,并使用花括号 {}
来嵌入 JavaScript 表达式。
JSX 会被 Babel 或类似的工具转译为普通的 JavaScript 代码,以便在浏览器中执行。这使得你可以在 React 项目中使用 JSX,而无需担心浏览器的兼容性。
不使用jsx创建元素
在 React 中,可以使用 React.createElement()
方法来创建 React 元素,而不使用 JSX。React.createElement()
方法接受三个参数:标签名(组件名或 HTML 标签名)、属性对象和子元素。
以下是一个使用 React.createElement()
创建 React 元素的示例:
import React from 'react';
const element = React.createElement('div', { className: 'my-class' }, 'Hello, World!');
console.log(element);
在上面的示例中,我们创建了一个 <div>
元素,其中包含一个 className
属性和文本内容 “Hello, World!”。React.createElement()
方法返回一个表示该元素的 JavaScript 对象,可以将其存储在变量中或传递给其他 React 组件进行渲染。
使用 React.createElement()
创建元素可以更直接地控制元素的创建过程,但由于需要手动编写 JavaScript 代码,可读性稍差。因此,大多数开发者倾向于使用 JSX 来描述 React 元素,因为它更直观和易于阅读。
稍微复杂一点就很头疼了,例如嵌套关系:
import React from 'react';
const element = React.createElement(
"div",
{ className: "my-class" },
React.createElement(
"div",
{ className: "my-calss-a" },
React.createElement(
"div",
{ className: "my-calss-b" },
React.createElement("div", { className: "my-calss-c" })
)
)
);
console.log(element);
所以还是推荐使用jsx创建React元素。
第4题: React.PureComponent 和 React.Component 有什么区别?
在 React 中,有两种主要的组件类:React.Component
和 React.PureComponent
。它们之间的区别在于它们在进行组件更新时的行为。
-
React.Component
:这是 React 中最基本的组件类。当组件的props
或state
发生变化时,React.Component
类会重新渲染组件。这意味着,即使组件的props
或state
没有实际变化,React 也会执行重新渲染。这可能会导致性能上的浪费,尤其是在组件层次结构较大或组件更新频繁时。 -
React.PureComponent
:React.PureComponent
是React.Component
的一个优化版本。它通过实现浅比较来避免不必要的重新渲染。当组件的props
或state
发生变化时,React.PureComponent
会使用浅比较来检查它们是否实际上发生了变化。只有当props
或state
发生真正的变化时,React.PureComponent
才会重新渲染组件。这可以减少不必要的渲染,提高性能。
需要注意的是,React.PureComponent
的浅比较只适用于 props
和 state
是不可变的数据类型(如基本类型、字符串、数组、对象等)。如果 props
或 state
包含可变的数据类型(如对象或数组的引用),则浅比较可能无法检测到变化。在这种情况下,建议使用 React.Component
。
总结起来,React.PureComponent
是一个性能优化的选择,适用于那些 props
和 state
是不可变的组件。如果组件的 props
或 state
经常发生变化,或者包含可变的数据类型,那么使用 React.Component
更合适。
扩展:
Component相当于需要手动实现 shouldComponentUpdate,而 PureComponent 通过浅对比默认实现了 shouldComponentUpdate 方法。
注意: 浅比较只比较了第一层,复杂数据结构可能会导致更新问题
什么是实际变化?
总结:指的是值的变化。
在 React 中,当组件的 props 或 state 发生变化时,React 会重新渲染组件。但是,并不是每次 props 或 state 发生变化时,组件都会重新渲染。React 使用一种称为"浅比较"的机制来确定是否应该重新渲染组件。
在 React 中,浅比较是通过比较 props 和 state 的引用来进行的。如果引用没有发生变化,React 将认为 props 或 state 没有实际变化,因此不会触发重新渲染。但是,如果引用发生变化,React 将认为 props 或 state 发生了实际变化,并触发重新渲染。
这意味着,如果你在每次更新时都创建一个新的对象作为 props 或 state,即使对象的值没有实际变化,React 也会认为 props 或 state 发生了变化,并触发重新渲染。相反,如果你在更新时保持相同的引用,那么即使值发生了变化,React 也不会触发重新渲染。
React.PureComponent 类是 React.Component 类的一个优化版本,它实现了浅比较的逻辑。当使用 React.PureComponent 时,如果组件的 props 和 state 与前一个 props 和 state 相等,React 将跳过重新渲染组件的过程。这可以提高性能,特别是在组件具有大量子组件或复杂的渲染逻辑时。
因此,实际变化是指组件的 props 或 state 引用发生变化,而不仅仅是值发生变化。
第5题:什么是 React?
React 是一个用于构建用户界面的 JavaScript 库。它由 Facebook 开发并开源,目的是为了解决构建大型、高性能的 Web 应用程序中的界面问题。
React 的主要特点是使用组件化的方式构建用户界面。通过将界面拆分成独立的、可重用的组件,React 提供了一种简单且高效的方式来构建复杂的用户界面。每个组件都有自己的状态(state)和属性(props),并且可以通过更新状态和传递属性来实现交互和数据流动。
React 还引入了虚拟 DOM(Virtual DOM)的概念,它是一个轻量级的内存中表示界面的数据结构。React 使用虚拟 DOM 来跟踪界面的变化,并通过比较前后两个虚拟 DOM 的差异来最小化实际 DOM 的更新。这种优化手段使得 React 在性能上表现出色,并且能够处理大规模的数据更新。
除了构建 Web 应用程序,React 还可以用于构建原生移动应用程序(React Native)和其他平台的应用程序。React 的设计理念和核心思想也影响了其他类似的前端框架和库。