组件生命周期

虚拟 DOM

正如我们从前面的示例中学到的,组件的 render 方法返回一个组件规范树。React 框架将这些规范转换为实际的 DOM 元素(对于 React JS)或原生控件(对于 React Native)。

我们还在前面的示例中看到,每当 props 更改或通过 setState 方法修改内部状态时,都会调用 render 方法。如果这些更改中的每一次都导致 DOM 元素或原生控件的解除分配和重新分配,那将非常低效。React 通过在组件规范树中首次出现时分配 DOM 元素或控件,并在不再出现在规范树中时才解除分配,从而避免了这种开销。任何其他更改都会导致轻量级更新。

React 如何知道组件实例是否已存在,或者是否需要更新?它利用了虚拟 DOM,它是组件规范树的一个缓存实例。通过简单的差异化逻辑,它可以有效地确定该树中的节点是否需要添加、删除或更新(当 props 更改时)。

组件列表给 React 的树差异化方法带来了有趣的挑战。差异化算法如何有效地检测组件移动到列表中新位置的情况?这是通过使用来完成的。键是一个字符串,它在列表中唯一标识一个组件实例与列表中的其他组件。每当返回相同类型的子组件列表时,渲染方法都必须指定一个键。

在此示例中,为列表中的每个用户渲染一个 UserInfoCard 组件。每个 UserInfoCard 实例都根据与每个用户对应的唯一 ID 获得一个键。

render() {
    var users = _.map(this.state.userList, user => {
        return (
            <UserInfoCard
                key={ user.id }
                user={ user }
            >
        );
    });

    return (
        <RX.View>
            { users }
        </RX.View>
    );
}

挂载与卸载

当 React 遇到一个在当前虚拟 DOM 中没有对应节点的组件规范时,它会将该规范插入虚拟 DOM。它还会分配一个相应的 DOM 元素(对于 React JS)或原生控件(对于 React Native)。这被称为挂载组件。同样,当组件实例从真实的 DOM 或原生控件层次结构中移除时,它被称为卸载。某些方法(如 setState)只能在组件挂载时调用。

React.Component 基类(所有组件都派生自该类)定义了几个方法,这些方法在组件挂载之前和之后以及组件卸载之前被调用。如果需要,组件类可以覆盖这些方法。例如,如果您想将焦点设置到文本输入框,可以在 componentDidMount 方法中完成。

protected componentWillMount();
protected componentDidMount();
protected componentWillUnmount();

更新

以前挂载的组件可以通过两种方式更新——通过修改其 props 或其 state。默认情况下,React 对 props 和 state 进行深度比较,以确定它们是否已更改。组件可以覆盖此行为,以根据对组件更详细的了解提供优化的比较逻辑。

protected shouldComponentUpdate(nextProps: P, nextState: S);

一旦确定组件应该更新,它会在更新之前和之后被通知。

protected componentWillReceiveProps(props: P);
protected componentWillUpdate(nextProps: P, nextState: S);
protected componentDidUpdate(prevProps: P, prevState: S);