写在前面:好久没写React,相关的基础知识都快忘的差不多了,乘着今天不忙,将官方的英文指南过一遍(注意:不是翻译!)

Why React

React的构建是用来解决一个问题: 构建数据实时更新的大型应用

介绍JSX

考虑一下下面的变量表达式:

1
const element = <h1>Hello, simmer!</h1>;

这个有趣的标签语法既不是字符串也不是HTML,实际上它叫做JSX,是一个JavaScript的语法扩展。看起来JSX是一个模版语言,但是它支持全面的JavaScript语法。

JSX中的嵌套表达式

你可以在JSX中通过大括号嵌套任何JavaScript语法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}

const user = {
firstName: 'Harper',
lastName: 'Perez'
};

const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);

ReactDOM.render(
element,
document.getElementById('root')
);

我们通过括号包裹JSX,并且为了可读性将它拆分成多行,这也有助于避免分号的自动插入。

JSX也是一个表达式

在编译以后,JSX表达式将会变成常规的JavaScript对象。

在JSX中指定属性

  • 可以通过引号来表达一个存文本的属性值
  • 也可以使用大括号来嵌套JavaScript表达式作为属性值

在JSX中指定子元素

  • 空标签可以使用/>闭合标签
  • JSX标签也可以包含子元素
1
2
3
4
5
6
const element = (
<div>
<h1>Hello!</h1>
<h2>Good to see you here.</h2>
</div>
);

警告
由于JSX比HTML更接近JavaScript, React DOM 使用驼峰属性命名规则而不是HTML的属性名,例如 在JSX中class变成了classNametabindex变成了tabIndex.

JSX 防止注入攻击

默认情况下,在渲染前React DOM会阻止在JSX中嵌入任何值。

渲染元素

元素是构建React应用的最小化模块。

1
const element = <hello , simmer />;

不同于浏览器的DOM元素,React元素是纯对象并且创建所花费的代价很小。 React DOM则更关心根据React元素来更新DOM。

提示
一个可能会使得元素变得疑惑的点是被更加广泛熟知的‘组件’概念。我们将会在下一届介绍组件。组件是通过元素来构成的,并且我们鼓励你在跳到后面内容前先阅读本节内容。

渲染一个元素到DOM中

为了渲染一个React元素到DOM根节点,将他们同时传入ReactDOM.render()中。

1
2
3
4
5
const element = <h1>Hello, world</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);

更新渲染元素

React元素是不可变的,一旦你创建了一个元素后就无法改变它的子元素或者属性。这就像是电影里的一帧,代表的是在某一时刻的UI。
目前我们熟知的更新UI的方法是创建一个新的元素并且把它传到ReactDOM.render()中。

组件和属性

组件让你将UI拆分为独立的,可复用的,可已独立思考的模块。
从概念上讲,组件就像是JavaScript函数。他们接受任意的输入(叫做’Props’)并且返回能描述当前UI表现的React元素。

Functional and Class Components

1
2
3
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
1
2
3
4
5
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

渲染一个组件

在前面我们遇到的React元素仅仅代表DOM标签

1
const element = <div/>''

然而,元素也可以代表用户定义的组件。

1
const element = <Welcome name="Sunny" />;

当React发现某一个原属代表的是一个用户定义好的组件,并且将JSX的属性作为一个对象传递到组件中。我们叫这个对象为”props”。

下面是一个栗子,它渲染”Hello, Sunny”到页面中。

1
2
3
4
5
6
7
8
9
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sunny" />;
ReactDOM.render(
element,
document.getElementById('root')
);

让我们来简要概括一下在这个栗子中发生了什么:

  • 我们调用ReactDOM.render()并且传递<Welcome name="Sunny" />这个元素到其中。
  • React 调用Welcome组件并且将{name: "Sunny"}作为props传递到组件中。
  • 组件Welcome返回<h1>hello, Sunny</h1>元素作为结果。
  • ReactDOM 有效率的更新DOM来匹配<h1>hello, Sunny</h1>

编写组件 && 解构组件

  • 组件嵌套
  • 将组件进行拆分,可以有效的复用组件

    Props是只读的

    看一个简单的函数:
    1
    2
    3
    functon addResult(a. b) {
    return a +b;
    }

上面的函数被叫做是纯函数因为他们不会试图去改变输入,并且同样的输入总会有同样的输出。

为了反映他们的props,所有的React组件必须按表现的像一个纯函数一样。

状态和生命周期


tips: 如果你没有在render方法中没有使用一些数据,那么它们就不该出现在state

正确的使用State

不要直接修改State

1
2
3
4
5
6
this.state.comment = "hello"; // wrong
```
上面的方法将不会触发React的重新渲染,所以应该使用以下方法:
```js
// Correct
this.setState({comment: "hello"});

状态的更新可能是异步的

为了性能方面的考虑,React可能会将批量的setState()方法合并为一次简单的更新。
也正是由于this.propsthis.state可能是异步更新的,你不能根据它们的值来计算下一次的状态。

1
2
3
4
// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});

为了修复这个问题,我们可以用第二种方法来调用setState(),那就是传递一个函数而不是一个对象进去。这个函数将会接受前一时刻的state最为第一个参数,更新被应用时的props作为第二个参数。

1
2
3
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment // Correct
}))

State的更新是一次合并

当你调用setState()方法的时候,React将会合并你提供的对象到当前的state中。
注意: state的合并是浅合并。

处理事件

首先注意在JSX中的事件和处理DOM的事件有些不同。

  • React事件的取名是驼峰式的,不是小写方式的。
  • 在JSX中传递一个函数作为事件处理函数,而不是字符串。
  • 在React中不能通过返回false来阻止浏览器的默认行为,而是需要使用preventDetault

使用ES2015 class语法定义组件,一般的建议是在constructor中绑定好事件处理的handler/或者使用箭头函数

有条件的渲染

列表和key

表单

区分受控表单和非受控表单的区别

提取公共状态

通常,如果组件需要重新渲染,我们首先会想到添加一个state到组件中。接着,当其他的组件也需要这个状态的时候,最好的做法是将状态提升到它们(组件)最近的共同祖先,而不是是这在不同的组件之间尝试同步状态,换句话说,你需要依靠这种自上而下的数据流。

组成 Vs 继承

未完待续