对 React 的初步理解

通过 JavaScript 写页面

在 React 中,页面的编写被融入进 JavaScript 代码。

比如在一个 HTML 网页,写一个如下的简单界面元素(标签):

1
2
3
<h1>
没错,这就是一个简单的标签。
</h1>

在 React,会这样写:

1
let element = React.createElement('h1', null, "没错,这就是一个简单的标签。");

而在 HTML 中,要使如上的 h1 标签在网页上展示出来,一般会放到网页结构里:

1
2
3
4
5
6
7
8
9
<html>
<head>
</head>
<body>
<h1>
没错,这就是一个简单的标签。
</h1>
</body>
</html>

在 React 中,需要使用 ReactDOM.reander() 函数:

1
2
3
4
5
let element = React.createElement('h1', null, "没错,这就是一个简单的标签。");
ReactDOM.render(
{element}
document.getElementById('root')
);

而 React 引入的 JSX 其实是对 React.createElement() 的封装,上面的效果如果使用 JSX,代码可能会是这样:

1
2
3
4
5
let element = <h1>没错,这就是一个简单的标签。</h1>
ReactDOM.render(
{element}
document.getElementById('root')
);

看上面这段代码,我们写 HTML 标签的方式和以往在 HTML 页面中编写是类似的,让人稍微惊讶的是,它 将标签赋值给了一个 JavaScript 变量 。这是 JSX 提供的写法。

回顾一下,按我的简单理解,React 做了一件事 —— 把 HTML 标签的编写融入 JavaScript,为此,提供了 React.createElement()

React 提供的 JSX 则对 React.createElement() 又进行封装,使 HTML 元素的编写符合以往的编写方式。(而不是传参这种别扭的方式)当然,JSX 的功能非常强大,条件渲染、列表渲染之类的这里就不细表了。

现在达到的效果便是:通过 JavaScript 写界面,且实际编写方式和以往在 HTML 中操作差别不大。

组件

将页面的编写纳入 JavaScript 后,界面和逻辑便被统一为 JavaScript 代码了。 一个组件往往封装了界面、状态、逻辑,在 Vue 中,一个组件就是一个 .vue 文件,而 在 React 中,一个组件就可以是一个 JavaScript 函数或者一个类

React 有两种组件:函数式组件,类组件。

还是拿上面的 HTML 标签举例,把它封装为一个函数式组件,可能是这样:

1
2
3
function Come(props) {
return <h1>没错,这就是一个简单的标签。</h1>;
}

封装为类组件则像是这样:

1
2
3
4
5
class Come extends React.Component {
render() {
return <h1>没错,这就是一个简单的标签。</h1>;
}
}

值得注意的是,所有的 React 组件都必须是 纯函数。纯函数意味着该函数对于给定的输入,都产生一个相同的输出。简单来说,该函数内部会用到的变量,外部都不能修改。不然即便每次都给一个确定的输入,外部改变了里面会用到的变量,它的输出也会有变化。[1]

这也是 React 强调的「数据的不可变性(immutable)」。

这儿函数内部的变量在 React 被称为 局部状态 。在官方文档 状态(State) 和 生命周期 中,由函数式组件引入到类组件,简单解释说「类定义的组件有一些额外的特性,比如局部状态。」。我觉得它为了入门把这儿简化了,因为函数式组件也可以通过闭包实现自己的局部状态……

可能我理解错了。

函数式组件和类组件从内部来说有什么区别,我也没深了解过。

将组件抽取为类后,组件的扩展就可以使用继承来实现了。 这点是不同于传统 HTML 编写的一个有趣之处。虽然 官方并不建议使用继承来扩展组件

总结

上面就是我对 React 的初步理解,也是我初次接触 React 感受到的,不同于我之前接触过的界面编写方式(传统界面编写方式、Vue)的地方。

当然,理解可能有误。 保持敬畏,先到这吧。


  1. 纯函数是函数式编程中一个核心概念。 ↩︎