文章目录
背景
什么是React
React是用于构建用户界面的JavaScript库,起源于Facebook的内部项目,已经于GitHub上开源。
官网
中文官网地址:https://zh-hans.reactjs.org/
GitHub项目地址:https://github.com/facebook/react/
资料
快速开始:https://zh-hans.reactjs.org/docs/getting-started.html
核心概念教程:https://zh-hans.reactjs.org/docs/hello-world.html
动手实例教程:https://zh-hans.reactjs.org/tutorial/tutorial.html
核心技术
JSX
概念
JSX,是一个 JavaScript 的语法扩展。
举例:const element = <h1>Hello, world!</h1>;
嵌入表达式
使用{}来嵌入变量或表达式。
举例:const element = <h1>Hello, {name}</h1>;
JSX 也是一个表达式
- 可以在 if 语句和 for 循环的代码块中使用 JSX
- 将 JSX 赋值给变量
- 把 JSX 当作参数传入
- 从函数中返回 JSX
JSX 中指定属性
使用 camelCase(小驼峰命名)来定义属性的名称,如 className。
有且只有如下两种形式:
// 字符串:同HTML语法
const element = <a href="https://www.reactjs.org"> link </a>;
// 大括号:外面无须引号
const element = <img src={user.avatarUrl}></img>;
JSX 防止注入攻击
在React中,所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(cross-site-scripting, 跨站脚本)攻击。
组件
概念
元素是构成 React 应用的最小砖块,例如原生的 DOM 标签,自定义组件。
组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。
组件的代码定义
组件名称必须以大写字母开头。(小写字母开头的会被视为原生 DOM 标签。)
有如下两种方式,且可以相互等价转换:
// 函数:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// 类:
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
将函数组件转换成 class 组件
- 创建一个同名的 ES6 class,并且继承于 React.Component。
- 添加一个空的 render() 方法。
- 将函数体移动到 render() 方法之中。
- 在 render() 方法中使用 this.props 替换 props。
- 删除剩余的空函数声明。
使用组合而非继承来实现组件间的代码重用
Props
Props的代码定义
当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
举例:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
JSX 中的子元素
子元素会作为特定属性 props.children 传递给外层组件。
举例:
// MyComponent 中的 props.children 是一个简单的未转义字符串 "Hello world!"。
<MyComponent>Hello world!</MyComponent>
Props 的只读性
决不能修改自身的 props。
State
数据是向下流动的
State 是私有的,并且完全受控于当前组件,其他组件包括父组件和子组件都无法感知和修改当前组件的State。
组件可以把它的 state 作为 props 向下传递到它的子组件中,而 props 又具有只读性。这通常会被叫做“自上而下”或是“单向”的数据流。
如果你把一个以组件构成的树想象成一个 props 的数据瀑布的话,那么每一个组件的 state 就像是在任意一点上给瀑布增加额外的水源,但是它只能向下流动。
State 每次只需更新部分变量
当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state。即可以只更新state中的某个变量。
不要直接修改 State
构造函数是唯一可以给 this.state 赋值的地方。
// 错误:
this.state.comment = 'Hello';
// 正确:
this.setState({comment: 'Hello'});
State 的更新可能是异步的
// 错误:
this.setState({
counter: this.state.counter + this.props.increment,
});
// 正确:
this.setState((state, props) => ({
counter: state.counter + props.increment
}));
生命周期方法
- componentDidMount() 方法会在组件已经被渲染到 DOM 中后运行;
- componentWillUnmount() 方法会在组件从DOM中移除之前运行;
React 元素的事件处理
定义
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
举例:
<button onClick={activateLasers} />
事件函数内使用this时需要先绑定
在构造函数中执行以下代码进行绑定:
// 为了在this.handleClick函数中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
向事件处理程序传递参数
方法:
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
组件列表
依据数组来渲染多个组件
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number, index) =>
<li>{number}</li>
);
依据map来渲染多个组件
const numbersMap = {a: 1, b: 2, c: 3, d: 4, e: 5};
const listItems = Object.keys(numbersMap).map((key, index) =>
<li>{numbersMap[key]}</li>
);
key 值在兄弟节点之间必须唯一
key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。
key 会传递信息给 React ,但不会传递给你的组件,使用 props.key 并不能获取。
一个好的经验法则是:在 map() 方法中的元素需要设置 key 属性。
受控组件
对于受控组件来说,输入的值始终由 React 的 state 驱动。
<input type=“text”>, <textarea> 和 <select> 之类的标签,它们都接受一个 value 属性,可以通过设置为 this.state.xxx ,变为受控组件。
你需要为数据变化的每种方式都编写事件处理函数,进行 State 的更新。(指定 value 属性后用户就无法在标签里输入更改)
状态提升
通常,多个组件需要 State 中某个变量同步变化 ,这时我们建议将该变量提升到最近的共同父组件的 State 中去。并且父组件在 props 中提供事件函数来允许这些组件通过调用该事件函数来更新 父组件 State。
React 不支持“双向绑定”,而是提供了“状态提升”的解决办法。这种解决办法需要编写更多的处理State的事件函数代码,优点是通过私有化和隔离 State,使得更容易排查定位 State 引起的问题。
Fragments
React 中的一个常见模式是一个组件返回多个元素。Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点。
举例:
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
进阶技术
深入JSX
实际上,JSX 仅仅只是 React.createElement(component, props, …children) 函数的语法糖。
举例,如下JSX代码:
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
会被编译为:
React.createElement(
MyButton,
{color: 'blue', shadowSize: 2},
'Click Me'
)
更多参见:https://zh-hans.reactjs.org/docs/jsx-in-depth.html
Context
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间共享数据的方法。(例如:地区偏好,UI 主题)
更多参见:https://zh-hans.reactjs.org/docs/context.html
错误边界
错误边界是一种在React 16 新引入的 React 组件,这种组件可以捕获发生在其子组件树任何位置的 JavaScript 错误,并打印这些错误,同时展示降级 UI,而并不会渲染那些发生崩溃的子组件树。
参见:https://zh-hans.reactjs.org/docs/error-boundaries.html
常见问题
配套资源
Ant Design
蚂蚁集团开源的一套基于React的UI库。
官网:https://ant.design/index-cn
GitHub项目:https://github.com/ant-design/ant-design