Build your own React_0 总述
Posted 一只前端小马甲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Build your own React_0 总述相关的知识,希望对你有一定的参考价值。
前端工程师的要求越来越高,仅懂得“三大马车”和调用框架API,已经远不能满足岗位的能力要求。因此增强自身的底层能力,了解框架的内部原理非常重要。本系列文章,翻译自Rodrigo Pombo的《Build your own React》一文,同时每篇文章最后,都会加入自己的理解,一方面记录自己初探React框架原理的过程,另一方面也是想与各位大牛多多交流,以出真知。
我们打算从零开始重写一个React框架,在遵循源码架构的基础上,省略了一些优化和非核心功能代码。
假设你阅读过我之前的文章《build your own React》,那篇文章是基于React 16.8版本,当时还不能使用hooks来替代class。
你可以在Didact仓库找到那篇文章和对应的代码。这里还有个相同主题的视频,跟文章的内容有些区别的,但是可以参考观看。
从零开始重写React框架,我们需要遵循以下步骤:
步骤零:总述
首先来回顾一些基本概念。如果你非常熟悉React、JSX和DOM元素的工作机制,可以直接进入步骤一。
我们使用一个简单的React示例,只有三行代码。首行定义了一个React元素,次行获取了一个DOM节点,最后一行将React元素渲染在容器中。
我们要做的是把所有的React代码改写为原生JavaScript代码。
const element = <h1 title="foo">Hello</h1>
const container = document.getElementById("root")
ReactDOM.render(element, container)
第一行我们定义了JSX语法的一个元素,但是并不是合法的javascript语法,因此我们需要做些修改。
const element = <h1 title="foo">Hello</h1>
// const container = document.getElementById("root")
// ReactDOM.render(element, container)
JSX通过类似于Babel这样的打包工具转化为JS代码。转化过程通常也很简单:将标签部分的代码代为调用createElement函数,原标签名、props和children属性作为参数。
const element = React.createElement(
"h1",
{ title: "foo" },
"Hello"
)
// const container = document.getElementById("root")
// ReactDOM.render(element, container)
React.createElement的作用在于生成一个JS对象。我们不考虑校验问题,因此完全可以用对象代替函数调用的结果。
const element = {
type: "h1",
props: {
title: "foo",
children: "Hello",
}
}
// container = document.getElementById("root")
// ReactDOM.render(element, container)
上面所说的React元素,实质上是个JS对象,具有type和props属性(可能有更多,但是我们目前只考虑这两个)。
type属性是个字符串,表示创建的DOM节点的类型,也是传给document.createElement函数的第一个参数tagName(标签名称)。
props属性是个对象,表示传递给节点的属性,它存储了所有从JSX传递来的键值对,同时有个特殊属性children。
children属性是可以是字符串,也可以是元素数组。这是React元素的数据结构为树的原因。
另外需要替换的React代码是ReacDOM.render。
ReactDOM.render(element, container)
render函数是React修改DOM的函数,现在让我们自己实现一次。
- 首先根据元素type创建一个节点,这个例子是h1。
- 然后将元素的props属性赋给DOM节点,这个例子中只有title。
- *为了避免歧义,我们使用元素指代React元素,节点指代DOM节点
const element = {
type: "h1",
// props: {
title: "foo",
// children: "Hello",
//},
}
const container = document.createElement(element.type)
node["title"] = element.props.title
// const text = document.createTextNode("")
// text["nodeValue"] = element.props.children
接着根据children属性创建子节点,这个例子中children属性值是字符串,因此只需要创建一个文字节点。
使用textNode而不是innerhtml保证了所有元素都能按照这种逻辑处理,我们处理nodeValue的方式跟处理之前h1标签的title属性一样,可以看作字符串拥有的props属性为:{ nodeValue: “Hello” }
const element = {
//type: "h1",
//props: {
//title: "foo",
children: "Hello"
//}
}
//const container = document.getElementById("root")
//const node = document.createElement(element.type)
//node["title"] = element.props.title
const text = document.createTextNode("")
text["nodeValue"] = element.props.children
最后,我们将textNode添加至h1,h1添加至container,得到了JavaScript改造后的程序。
const element = {
type: "h1",
props: {
title: "foo",
children: "Hello"
}
}
const container = document.getElementById("root")
const node = document.createElement(element.type)
node["title"] = element.props.title
const text = document.createTextNode("")
text["nodevalue"] = element.props.children
node.appendChild(text)
container.appendChild(node)
总结
步骤零使用一个小例子,展示了React元素的本质是JS对象,React根据JS对象中的信息去生成DOM树,而生成树的过程就是我们最熟悉的JS语法,例如:createElement、createTextNode、appendChild这些常见的api。
JSX语法 | JS语法(本质) |
---|---|
了解这个工作过程是非常重要的,首先这是后面章节学习的基础,其次也能让我们慢慢体会到React的设计哲学。来,准备单脚踏入React的大门了:)
以上是关于Build your own React_0 总述的主要内容,如果未能解决你的问题,请参考以下文章
Build your own React_4 理解React纤维