React 运行机制
React 的本质就是用于更新DOM的一个库
单页应用
说起 React,可能不得不说说单页应用(single-page application, SPA),但是单页应用又是怎么演变以来的呢?那我们来扒一扒这个过程。
话说很久很久以前(也就是在28年前的昨天),世界上第一个网页诞生,...。
哈哈哈,开个玩笑,搞不了这么久远。在过去,网页是有互相独立的HTML文档构成的页面,直到,AJAX 的发明才逐渐引入单页应用的概念。此处用一个我现在能想到的词语语来形容单页应用(换汤不换药),虽然目前的网页大多是现在的 单页应用,但是实际上还是利用 JavaScript 来更新,更改 HTML DOM,也就是本文开头第一句,总结一下当前普遍的单页应用,在一个HTML文档里边,应用一个更新DOM的库来渲染与重渲染的网页应用。
React 元素
我相信,绝大部分人原来常用语更新DOM 的都是用的 document.createElement 或 document.appendChild 等 DOM API。浏览器的 DOM 由 DOM 元素组成,类似地, 而 ReactDOM 则由 React 元素组成,最终由 ReactDOM 中的 render 方法 将 React 元素 转换为真正的 DOM 元素。
创建一个 React 元素:
js
const hellowH1 = React.createElement('h1', { id: 'helloReact' }, 'Hello React!');
console.log(hellowH1);
/**
{
$$typeof: Symbol(React.element),
"type": "h1",
"key": null,
"ref": null,
"props": {id: "helloReact", children: "Hello React!"},
"_owner": null,
"_store": {}
}
*/
而渲染出来的真正的DOM元素是:
html
<h1 id="helloReact">Hello React!</h1>
我们可以看到 上面 hellowH1 元素对象中的 type 与 props 属性中 的值, 跟 真正的 DOM 元素中是否能联想出,他们之间绝对存在着某种不可告人的关系。 type 属性告知 React 要创建的是什么类型的 HTML 或 SVG 元素。props 属性表示构建一个 DOM 元素所需要的数据和子元素。
ReactDOM
创建 React 元素之后,ReactDOM 提供了在浏览器中渲染 React 元素所需要的工具(ReactDOM.render 方法)。
js
const hellowH1 = React.createElement('h1', null , 'Hello React!');
ReactDOM.render(dish, document.getElementById("root"));
ReactDOM.render 方法将 React 元素 dish 挂载到 id 为 "root " 的节点上。第一个参数 就是一个或多个 React 元素。当 React 元素为多个时,第一个参数就传入 React 元素 数组。
子元素
举个例子就很好理解:
js
const todoList1 = React.createElement(
'ul',
null,
React.createElement('li', null, '看书'),
React.createElement('li', null, '写文章'),
React.createElement('li', null, '健身'),
React.createElement('li', null, '练习毛笔字'),
React.createElement('li', null, '练习萨克斯')
);
const todoList2 = React.createElement(
'ul',
null,
[
React.createElement('li', null, '看书'),
React.createElement('li', null, '写文章'),
React.createElement('li', null, '健身'),
React.createElement('li', null, '练习毛笔字'),
React.createElement('li', null, '练习萨克斯'),
]
);
const todoItems = ['看书', '写文章', '健身', '练习毛笔字', '练习萨克斯'];
const todoList3 = React.createElement(
'ul',
null,
todoItems.map((item, i) => React.createElement('li', { key: i }, item))
);
我们可以以各个额外的参数作为多个子元素,也可以以数组来整体作为子元素,还可以通过数据构造子元素。
React 组件
程序员的CV大法直接决定了水平的高低。我们的网页中经常会用到大量的重复DOM 结构,而组件的诞生就是为了解决重复性处理与维护的问题。如果还是单页面应用的时候,曾经类似的页面你用了的CV大法当时有多舒服,那么在维护的时候,你可能就有多痛苦。而组件的诞生,也预示着维护成本的降低。 我们来看看这个todo的组件:
js
function TodoList(items) {
return React.createElement(
'ul',
{ className: 'todo-item' },
item.map((item, i) => React.createElement('li', { key: i }, item))
)
};
const todoItems = ['看书', '写文章', '健身', '练习毛笔字', '练习萨克斯'];
ReactDOM.render(
React.createElement(
TodoList,
{ items: todoItems },
null
),
document.getElementById("root")
);
当我们把这个组件定义好的时候,我们每天的待办事项都不同,也就是我们每天只需要更新 todoItems 这个变量的值 就可以展示每天不同的啦待办事项。
总结
React 的本质就是用于更新DOM的一个库
- 单页应用:在一个HTML文档里边,应用一个更新 DOM 的库来渲染与重渲染的网页应用。
- React 元素:ReactDOM 转换为真实 DOM 的元素,由子元素,类型,属性等构成。
- ReactDOM:将 React 元素转换为真实 DOM 的工具。
- 子元素:可以有单个,多个,数据构造组成。
- React 组件:由多个子元素组合成的固定结构。(便于数据更新,重复调用,以及维护)。