React的设计思想核心在于组件和虚拟DOM。组件允许把UI切分成独立且复用的代码片段,虚拟DOM在内存中模拟DOM结构,避免直接操作真实DOM。
一、模块化设计:React通过ES6的class和module语法组织代码。例如ReactDOM模块管理DOM操作,Component模块是所有组件的基类。
/** js */
import ReactDOM from 'react-dom';
import { Component } from 'react';
二、JSX语法:JSX是JavaScript XML的简写,React使用JSX来声明式地构建用户界面。Babel会把JSX编译成React.createElement()方法来创建虚拟DOM元素。
/** jsx */
const element = <h1>Hello, world!</h1>;
三、组件机制:React应用由多个组件构成,包括函数组件和类组件。类组件继承React.Component,定义render()方法返回JSX;函数组件就是普通的JS函数,接收props并返回JSX。无论类组件还是函数组件,都可以通过props接收数据和回调,通过state管理内部状态。这种组件化结构,使UI可以划分为独立且复用的部分。
/** jsx */
// 函数组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// 类组件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
四、状态管理:React使用state对象存储组件状态,调用this.setState()触发UI更新。渲染和状态在React中深度绑定,使其成为一个数据驱动的UI库。
/** jsx */
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: 0 };
}
tick() {
this.setState({ seconds: this.state.seconds + 1 });
}
}
五、虚拟DOM:为了高效更新UI,React将DOM对象转化为JavaScript对象(虚拟DOM)来描述,setState()会触发整个虚拟DOM重新渲染。React利用虚拟DOM Diff算法计算出真实DOM需要更新的部分,避免频繁操作真实DOM,这是React性能高的关键。
/** jsx */
const element = {
type: 'h1',
props: {
className: 'greeting',
children: 'Hello, world!'
}
};
六、生命周期:React组件生命周期分为三个阶段:初始化、更新和卸载。不同阶段会自动调用不同方法,如componentDidMount()、shouldComponentUpdate()、componentWillUnmount()等,方便在对应时期执行必要逻辑。
/** jsx */
class Clock extends React.Component {
// 通过调用super()继承React.Component
constructor(props) {
super(props);
// 定义初始状态
this.state = {date: new Date()};
}
// 组件挂载完毕时触发
componentDidMount() {
// 启动定时器
this.timerID = setInterval(
// 通过setState()触发重渲染
() => this.tick(),
1000
);
}
// 组件更新时触发
componentDidUpdate() {
// ...
}
// 组件卸载前触发
componentWillUnmount() {
// 清除定时器
clearInterval(this.timerID);
}
// 重新渲染组件
tick() {
this.setState({
date: new Date() // 设置新的状态
});
}
// 返回组件UI
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
七、高阶组件:高阶组件是React组件中高级技巧,本质上是一个函数,接收一个组件,并返回一个新的组件。利用高阶组件可以抽象出通用逻辑,增强复用性。
/** jsx */
const hocComponent = (WrappedComponent) => {
class HOC extends React.Component {
// ...
}
return HOC;
}
八、context:Context通过组件树上下文,可以避免通过中间组件传递props。React.createContext()创建上下文,使用时需要在上层组件设置Provider,在下层组件设置Consumer。
/** jsx */
// 创建上下文
const MyContext = React.createContext();
// 中间组件
<MyContext.Provider value={/* 某个值 */}>
// 下层组件
<MyContext.Consumer>
{value => /* 基于上下文值进行渲染 */}
</MyContext.Consumer>
九、refs:ref可以绑定到DOM元素或React组件实例上。使用它可以执行 DOM操作,或访问组件实例。
/** jsx */
// 绑定到DOM元素
<input ref={input => this.textInput = input} />
// 绑定到类组件
<MyComponent ref={component => this.myComponent = component} />
十、Fiber架构:Fiber是React 16推出的新组件架构。它为新的渲染机制服务于很好的平台。新的渲染机制的目标是增量渲染很大的组件树而不丢失状态,同时不会阻塞浏览器。
在旧版React中,渲染过程是同步的和阻塞的。这意味着在渲染过程中,浏览器不能执行其他任务,导致性能问题。
Fiber使用新的渲染机制,其工作原理如下:渲染工作被分割成多个“单元”(fibers),同一时间只会渲染一个单元,其他单元会暂停。这意味着浏览器可以在完成当前单元任务之前进行其他任务。这种机制被称为“增量渲染”。
每个fiber有3个状态:
1. Pending - 初始状态。意味着fiber还没有被处理。
2. Working - fiber正在被处理中。
3. Complete - fiber处理完成。
通过这三个状态,React可以中断和恢复渲染过程,实现增量更新。
fiber有两大作用:
1. 记录组件的状态,方便中断后恢复。
2. 链接其他fiber,通过sibling和child指针构成fiber树。
通过Fiber架构,React实现了增量渲染,解决了旧版阻塞渲染的问题,大大提高了这也使得React可以用于更加复杂和动态的应用场景。