type
status
date
slug
summary
tags
category
icon
password
Property
Mar 4, 2024 06:30 AM
前言
之前我们已经用比较规范的方式实现了字符串和数字的渲染,接下来我们将渲染原生 DOM。
预备知识
正则
我们在匹配事件和 style 属性的时候,我们需要用到简单的正则知识点
- [A-Z] 大写字母
- ^ 以**开头
除了使用正则的 test 判断以外,我们还可以和String.place搭配使用。注意:这个方法不会改变原字符串。
jquery 事件的命名空间和事件代理
在元素创建的时候,我们会在 document 上采用事件委托绑定事件(后面会解释原因),元素移除的时候我们还要移除事件。为了简便操作我们会用命名空间来实现。
原理分析
我们在写 React 的代码的时候,我们一般会写 JSX.而在我们的现在开发中,会经过 babel 等转换为 React.createElement 代码。这也就是 JSX 的作用,简单可以理解为 React.createElement 的语法糖。
我们用下面的代码示例
而如果我们直接在代码中打印这个
element
会是什么样子呢?代码可以看这里可以看到,打印出来是一个对象,里面有
$$typeof、key、type、props
等等很多属性。而我们需要关注的是 type
属性和 props
属性,甚至可以可以看到,props
里面有个 children
属性,而且可以继续展开,里面就是层层递进的 children
子元素。其实这个对象就是虚拟 DOM,在后面更新的时候我们也会说到。至此我们也有了一个大概的流程。
和之前的字符串的渲染对比得知,我们这次渲染的是
React.createElement
的返回值,它的返回值是一个实例,我们现在称为 Element
实例。动手实现
经过上述的分析,我们得到此次渲染原生 DOM 我们需要做的事情后大致如下
我们这次渲染的代码为
createElement
我们在 react 文件夹新建 element.js,这个函数的作用就是根据将所有传入的参数实例化,返回一个对象 代码如下:
再在 react/index.js 引入 createElement,方便调用。
createUnit
createElement 函数调用完成之后,我们就要进入 createUnit 工厂函数来进行判断生成实例
这个地方我们要注意,这个时候的 element 是 Element 的实例,因此我们可以用 instanceof,而且渲染的都是原生的 DOM,因此 tag 名称都是字符串,我们可以使用 element.type 辅助判断。
NativeUint
经过 createUnit 工厂函数之后我们就要生成 NativeUint 了,我们写一个 NativeUint 的 class。我们仍然是继承了 Unit,将元素存到了
this._currentElement
调用实例 getMarkUp
在这一步我们需要调用 getMarkUp。我们先想想我们这个步骤的大概流程。
我们之前说过,我们的 getMarkup 函数需要传入一个
key
,然后返回一个
字符串
。对这就是最直观的理解,而返回的字符串可能就是下面的样子。
我们最终需要的字符串大概为:
,包含了一个闭合的 tag,上面还有一些属性,我们就需要遍历添加属性,还要添加对应的唯一 id,还要对 children 子元素做处理。
我们理一下:
- 原生 DOM,要根据渲染对应的 tag
- style 等 css 处理
- class 等属性梳理
- 事件绑定 为什么要事件委托,因为开始的时候元素还只是个字符串,无法绑定事件
- children 的处理
- 其他属性
我们添加 getMarkup 函数,现在我们讲解这部分代码。
最后渲染
结语
顺着以上的思路,我们成功渲染了原生 DOM,事件、样式、类名等等都一一成功渲染出来。而原生 DOM 的渲染看起来还是有点点复杂,就是深度优先,直接递归,直到没有元素方才完成使命。
本节代码地址:代码地址
今天,我们成功完成了原生 DOM 的渲染,接下来我们将处理 Class Component,敬请期待吧!
- 作者:Kitety
- 链接:https://www.kitety.com/article/realize-your-own-react-rendering-native-dom
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。