页面的渲染逻辑(HTML)从根上是和 UI 交互逻辑(JavaScript)耦合的,事件如何处理、状态如何转移、数据如何加工决定了页面的最终呈现。React 组件同时包含了 HTML 和 JavaScript。
JSX 是 JavaScript 的扩展,用于产生描述 UI 的 React 元素。JSX 在编译后会变成普通的函数调用(React.createElement()
),得到的结果是一个 JavaScript 对象(也就是 React 元素),React 读取这些对象来构建、更新 DOM。同时这也意味着 JSX 可以用在 if
语句和 for
循环中、赋值给变量、函数的参数和返回值。
|
|
React 在渲染 JSX 中包含的变量的值之前会进行字符跳脱,因此可以安全地在 JSX 中使用用户的输入而不必担心 XSS 攻击。
React 元素是 React App 的最小构成要素,由于它只是普通的 JavaScript 对象,因此创建的开销很低(这一点和 DOM 元素不同),React DOM 根据 React 元素所描述的信息去更新 DOM。
|
|
纯 React 应用通常只有一个 root DOM 元素;React 应用通常只会调用一次 ReactDOM.render()
。
React 元素不可变,创建后即不可更改它的子元素、属性,它表示的是某个时间点下的 UI 快照。通过比较 React 元素变化前后的的信息,React 只会对 DOM 做必要的更新,而不是重新构建整个 DOM。
React 组件接收任意输入(props
)并返回 React 元素。有 2 种类型的 React 组件:
函数组件
1 2 3
function Welcome(props) { return <h1>Hello, {props.name}</h1>; }
class 组件
1 2 3 4 5
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.state
(this.setState()
触发)的更新会触发 render()
方法的执行——比较前后 React 元素的变化,计算出更新的部分并渲染页面。
可以参照单一职责原则来划分 React 组件。
构建 React App 过程拆解:
- 将 UI 拆解成得到一个个划分层级的 React 组件;
- 构建静态版本的的 App;
- 此阶段只使用
props
在组件间传递状态,暂不使用state
(它是用作交互的);此时的 class 组件只有一个render()
方法。 - 此阶段的输出是可复用的 React 组件。
- 此阶段只使用
- 按照 DRY 原则确定出最小完整状态(
state
); - 确定
state
应该归属于哪个组件; - 添加数据流的反向更新逻辑。
- React 采用单向数据流的模型:数据由父组件单向地向子组件流动,子组件只能通过父组件经由
props
传递下来的函数(callback)来更新归属于父组件的状态(state
)。 - 和双向绑定相比,单向数据流需要多写一些模板代码,但数据的流向更清晰,方便定位问题。
- React 采用单向数据流的模型:数据由父组件单向地向子组件流动,子组件只能通过父组件经由