页面的渲染逻辑(HTML)从根上是和 UI 交互逻辑(JavaScript)耦合的,事件如何处理、状态如何转移、数据如何加工决定了页面的最终呈现。React 组件同时包含了 HTML 和 JavaScript。

JSX 是 JavaScript 的扩展,用于产生描述 UI 的 React 元素。JSX 在编译后会变成普通的函数调用(React.createElement()),得到的结果是一个 JavaScript 对象(也就是 React 元素),React 读取这些对象来构建、更新 DOM。同时这也意味着 JSX 可以用在 if 语句和 for 循环中、赋值给变量、函数的参数和返回值。

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
)
// 等价于:
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
)

React 在渲染 JSX 中包含的变量的值之前会进行字符 跳脱 ,因此可以安全地在 JSX 中使用用户的输入而不必担心 XSS 攻击

React 元素是 React App 的最小构成要素,由于它只是普通的 JavaScript 对象,因此创建的开销很低(这一点和 DOM 元素不同),React DOM 根据 React 元素所描述的信息去更新 DOM。

// some html
// <div id="root"></div>

// 将名为 element 的 React 元素渲染到 id 为的 root 的 DOM 元素中;
// root DOM 中的内容由 React DOM 管理。
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

纯 React 应用通常只有一个 root DOM 元素;React 应用通常只会调用一次 ReactDOM.render()

React 元素 <strong>不可变</strong> ,创建后即不可更改它的子元素、属性,它表示的是某个时间点下的 UI 快照。通过比较 React 元素变化前后的的信息,React 只会对 DOM 做必要的更新,而不是重新构建整个 DOM。

React 组件接收任意输入(props)并返回 React 元素。有 2 种类型的 React 组件:

  1. 函数组件

    function Welcome(props) {
        return <h1>Hello, {props.name}</h1>;
    }
    
  2. class 组件

    class Welcome extends React.Component {
        render() {
            return <h1>Hello, {this.props.name}</h1>;
        }
    }
    

React 元素可以是 DOM 元素(小写字母开头),也可以是自定义的 React 组件(大写字母开头)。对于后者,React 通过 props 对象将 JSX 属性和子元素(props.children)传递给该 React 组件。
props 对象的成员可以是 React 元素(就是普通的 JavaScript 对象)、函数、JavaScript primitive values。

一个组件返回的 React 元素中可以引用其它组件(叶子组件一定是 DOM 元素,通过 React.createElement() 创建出来)。

通常,新的 React 应用通常有一个位于顶层的 APP 组件。

不修改组件的 props 是必须要严格遵守的规定。

对于 class 组件,this.props(父组件传递过来)和 this.statethis.setState() 触发)的更新会触发 render() 方法的执行——比较前后 React 元素的变化,计算出更新的部分并渲染页面。

可以参照 单一职责原则 来划分 React 组件。

构建 React App 过程拆解:

  1. 将 UI 拆解成得到一个个划分层级的 React 组件;
  2. 构建静态版本的的 App;
    • 此阶段只使用 props 在组件间传递状态,暂不使用 state(它是用作交互的);此时的 class 组件只有一个 render() 方法。
    • 此阶段的输出是可复用的 React 组件。
  3. 按照 DRY 原则确定出最小完整状态(state);
  4. 确定 state 应该归属于哪个组件;
  5. 添加数据流的反向更新逻辑。
    • React 采用 单向数据流 的模型:数据由父组件单向地向子组件流动,子组件只能通过父组件经由 props 传递下来的函数(callback)来更新归属于父组件的状态(state)。
    • 和双向绑定相比,单向数据流需要多写一些模板代码,但数据的流向更清晰,方便定位问题。