React 入门(2): 状态 UI更新 类组件

状态

UI无非就是应用程序的状态的一种表现形式.
我们已经了解ReactDOM.render()函数可以挂载或局部更新DOM, 但是我们需要一种更精妙的方式.

第一种方式: 渲染并重绘整个根节点

每当应用程序状态有任何更新, 我们就刷新一次根节点, 这样是可以的, 毕竟React只会更新变化的节点, 但是整个树节点都进行一次比对是冗余的.
我们来看这种不推荐的方式:

import ReactDOM from 'react-dom';
import { StrictMode, createElement } from 'react';

document.body.innerHTML = `<div id="app"></div>`;

let count = 0;

function MyTitle() {
    return createElement('div', {
        style: {
            fontSize: '38px',
            color: '#880088',
            background: 'pink',
        },
    }, `我觉得不行 +${count}`, ' => ', createElement('button', {
        style: {
            fontSize: '38px',
        },
        onClick() {
            count++;
            render(); // 应用程序状态发生变化, 刷新根节点
        },
    }, '+1'));
}

function render() {
    ReactDOM.render(createElement(StrictMode, null, MyTitle()), app);
}
render(); // 立即挂载根节点

有没有其它方式

根据官网描述, 我们可以只调用一次ReactDOM.render挂载一个根节点, 那怎么更新UI呢?

官网还有以下一些论述:

React 元素是不可变对象。一旦被创建,你就无法更改它的子元素或者属性。一个元素就像电影的单帧:它代表了某个特定时刻的 UI。
根据我们已有的知识,更新 UI 唯一的方式是创建一个全新的元素,并将其传入 ReactDOM.render()。
React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。

更新 UI 唯一的方式是创建一个全新的元素

React.Component类定义了类组件的架构, 其中render()函数负责创建一个新的React元素, 只要我们遵循以下规则, 就可实现局部更新:

  • 通过setState()函数更新组件状态, React会调用render()函数创建新的元素
  • 必要时可调用forceUpdate()函数强制同步UI

类组件

/**
 * 类组件及其状态与UI的更新与同步
 */
import ReactDOM from 'react-dom';
import { Component, createElement } from 'react';

document.body.innerHTML = `<div id="app"></div>`;

class MyTitle extends Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
    }
    render() {
        console.log('render被调用');
        return createElement('div', {
            style: {
                fontSize: '38px',
                color: '#880088',
                background: 'pink',
            },
        }, `我觉得不行 +${this.state.count}`, ' => ',
            createElement('button', {
                style: {
                    fontSize: '38px',
                },
                onClick: () => { // 事件被绑定到DOM上时, this会丢失, 因此必须使用箭头函数.
                    this.setState({ count: this.state.count + 1 });
                    // 等价于:
                    // ++this.state.count && this.forceUpdate();
                },
            }, '+1'),
        );
    }
}

function render() {
    ReactDOM.render(createElement(MyTitle), app);
}
render(); // 立即挂载根节点

关于setState()函数

  • setState()可能是异步的
    出于性能考虑,React 可能会把多个 setState() 调用合并成一个调用。
    因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
    要解决这个问题,可以让 setState() 接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数。

END

posted @ 2020-09-01 15:38  develon  阅读(317)  评论(0编辑  收藏  举报