在 React.Component 的子类中有个必须定义的 render() 函数。React建议不要创建自己的组件基类。 在 React 组件中,代码重用的主要方式是组合而不是继承。
组件的生命周期
props-
APIs
setState()constructor()-
class 属性
-
- 为
Class 组件添加默认 props。这一般用于 props 未赋值,但又不能为 null 的情况。class CustomButton extends React.Component {// ...}CustomButton.defaultProps = {color: 'blue'};
- 为
-
参考
props<br />
需特别注意,this.props.children是一个特殊的 prop,通常由 JSX 表达式中的子组件组成,而非组件本身定义。
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
state
render()
该方法是 class 组件中唯一必须实现的方法。
当 render 函数被调用时,它会检查 this.props 和 this.state 的变化并return以下类型之一:
- React 元素:
- 如:
<div />会被 React 渲染为 DOM 节点,<MyComponent />会被 React 渲染为自定义组件;
- 如:
- 数组或 fragments:使得 render 方法可以返回多个元素。
- Portals:可以渲染子节点到不同的 DOM 子树中。
- 字符串或数值类型:它们在 DOM 中会被渲染为文本节点
- 布尔类型或
null:什么都不渲染。
注意:
render()函数应该为纯函数,即:在不修改组件state的情况下,每次调用时都返回相同的结果- 并且它不会直接与浏览器交互。
- 如果
shouldComponentUpdate()返回false,则不会调用render()。
constructor(props)
通常,在 React 中,构造函数仅用于以下两种情况:
- 在实现构造函数时,应在第一行调用
super(props),为什么? 在
constructor()函数中不要调用setState()方法。constructor(props) {super(props);// 不要在这里调用 this.setState()this.state = { counter: 0 };this.handleClick = this.handleClick.bind(this);}
避免将 props 的值复制给 state
- 可以直接使用
this.props.color```jsx constructor(props) { super(props); // 不要这样做 this.state = { color: props.color };
- 可以直接使用
}
<br /><a name="Y3dmB"></a>#### 为什么时应在构造函数第一行调用 `super(props)`**调用 super()**<br />这是 `JavaScript` 的限制,在构造函数里**如果要调用 **`**this**`,那么提前就要调用 super,<br />而在 `React` 里,常会在构造函数里**初始化 state**,`this.state = xxx` ,所以需要调用 super。<br />**<br />**传递 props**<br />`React` 会在`构造函数`**运行之后**,会把 `props` **赋值**给刚刚创建的**实例对象**;<br />但在构造函数**结束之前**, `this.props` 仍然是没法用的。**因此,建议始终使用**`**super(props)**`**,**确保 `this.props` 始终是有值的```jsx// React内部代码class Component {constructor(props) {this.props = props;...}}// 组件代码class Button extends React.Component {constructor(props) {super(); // 😬 忘了传入 propsconsole.log(props); // ✅ {}console.log(this.props); // 😬 undefined}...}
为避免以上的问题,也可以通过class属性 提案 来简化代码:
class Clock extends React.Component {state = {date: new Date()};render() {return (<h2>It is {this.state.date.toLocaleTimeString()}.</h2>);}}
setState(updater, [callback])
setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。这是用于更新用户界面以响应事件处理器和处理服务器数据的主要方式
将 setState() 视为请求而不是立即更新组件的命令。为了更好的感知性能,React 会延迟调用它,然后通过一次传递更新多个组件。React 并不会保证 state 的变更会立即生效。setState() 并不总是立即更新组件。它会批量推迟更新。这使得在调用 setState() 后立即读取 this.state 成为了隐患。为了消除隐患,请使用 componentDidUpdate 或者 setState 的回调函数(setState(updater, callback)),这两种方式都可以保证在应用更新后触发。如需基于之前的 state 来设置当前的 state,请阅读下述关于参数 updater 的内容。
除非 shouldComponentUpdate() 返回 false,否则 setState() 将始终执行重新渲染操作。如果可变对象被使用,且无法在 shouldComponentUpdate() 中实现条件渲染,那么仅在新旧状态不一时调用 setState()可以避免不必要的重新渲染
参数一为带有形式参数的 updater 函数:
(state, props) => stateChange
state 是对应用变化时组件状态的引用。当然,它不应直接被修改。你应该使用基于 state 和 props 构建的新对象来表示变化。例如,假设我们想根据 props.step 来增加 state:
this.setState((state, props) => {return {counter: state.counter + props.step};});
updater 函数中接收的 state 和 props 都保证为最新。updater 的返回值会与 state 进行浅合并。setState() 的第二个参数为可选的回调函数,它将在 setState 完成合并并重新渲染组件后执行。通常,我们建议使用 componentDidUpdate() 来代替此方式。setState() 的第一个参数除了接受函数外,还可以接受对象类型:
setState(stateChange[, callback])
stateChange 会将传入的对象浅层合并到新的 state 中,例如,调整购物车商品数:
this.setState({quantity: 2})
这种形式的 setState() 也是异步的,并且在同一周期内会对多个 setState 进行批处理。例如,如果在同一周期内多次设置商品数量增加,则相当于:
Object.assign(previousState,{quantity: state.quantity + 1},{quantity: state.quantity + 1},...)
后调用的 setState() 将覆盖同一周期内先调用 setState 的值,因此商品数仅增加一次。如果后续状态取决于当前状态,我们建议使用 updater 函数的形式代替:
this.setState((state) => {return {quantity: state.quantity + 1};});
forceUpdate()
component.forceUpdate(callback)
默认情况下,当组件的 state 或 props 发生变化时,组件将重新渲染。如果 render() 方法依赖于其他数据,则可以调用 forceUpdate() 强制让组件重新渲染。
调用 forceUpdate() 将致使组件调用 render() 方法,此操作会跳过该组件的 shouldComponentUpdate()。但其子组件会触发正常的生命周期方法,包括 shouldComponentUpdate() 方法。如果标记发生变化,React 仍将只更新 DOM。
通常你应该避免使用 forceUpdate(),尽量在 render() 中使用 this.props 和 this.state。
