-
Notifications
You must be signed in to change notification settings - Fork 384
preact 源码学习系列之一:JSX解析与DOM渲染 #103
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
React的代码结构看得我蛋疼。。。完全找不着北😂。 |
@javoski 我也是,满眼都是什么 React、Component 这些单词,看得眼都花了。 |
是不是应该把 |
@deot 引入概念 |
@youngwind 使用 |
imho, |
@shadeofgod 不是这样的,如果你一次性插入 |
@deot 没太明白你的意思。。。 |
@shadeofgod 好像又讨论了其他问题,我是指原生操作;
我的理解是:数据驱动,虚拟DOM更趋向的是提升了开发效率,减少开发者各种不必要的DOM操作达到性能提升 |
提升开发效率是因为框架帮我们完成了数据和视图之间的绑定,使得开发者只需要关注数据的变化,而数据到视图的映射利用了Virtual DOM这一思路来提升性能。 |
deot的观点很好。shadeofgod姿态很高,其实没有听出关键点,在自说自话。前天我就用ng1比较vue,循环1000次的变化,ng1完爆vue,估计很多网上的观点都是有前提的。并不是说真的就能搬过来的。 |
@william-xue 我有什么说错说漏的地方欢迎直接指出来,本来就是抱着学习交流的心态来的,单纯的文字很多时候都不能表达完整的感情色彩,技术上的事情我倾向于有问题放开了说清楚,没必要在别人的博文下说我姿态高把我批判一番。 |
@EzioKissshot 这里的代码是 bable5 编译之后的, |
@youngwind 谢谢! |
setAttributes(node, key, attrs[key]); 是不是引用了lodash之类的库? |
@william-xue 不是,此处代码没贴完整,setAttributes 是我自己定义的函数,详情看这里:https://github.com/youngwind/fake-preact/blob/master/preact.js#L189-L202 |
前言
一直以来我都想研究 React 的源码,但总是看不懂。即便是去翻看最早的源码,代码量也有1万多行,研究起来难度太高了,这个问题困扰了我很久。
直到前两天我跟同事讨论起这个问题,忽然发现一个可行的方法:React 的源码太难懂,可以看 preact 的源码啊!为什么呢?因为 React 代表的是一种思想,能实现这种思想的不只有 React。preact 便是一个 mini 版的 React,其代码量很少,目前也就 1000多行,但是已经实现了 React 的主要功能。
这的确是一个很不错的研究方法,值得推荐。那么,我们便按着这种思路来研究,此次参考的是 preact 2.0.1 版本。
目标
React 类框架功能很多,应该从哪个角度入手的。
答案:从“解析 JSX,渲染 DOM 入手”
举个例子:
问题是:给定一段 JSX 和一个挂载点,如何解析 JSX,生成真实 DOM 并挂载到页面中呢?
谁来解析 JSX
要想生成真实 DOM,必须有一个层级嵌套的对象,此对象表征了 DOM 的嵌套结构。我们只需要遍历此对象,便可拼接出 DOM。
问题是: 如何把这段 JSX 格式的字符串转化为对应嵌套结构的对象呢? 这本质上是 HTML 解析器所要完成的事情。然而,我无力实现一个 HTML 解析器,怎么办呢? → 答案是使用 babel。
babel 作为一个代码转换工具,它不仅仅能将 ES6 转化成 ES5,也能够将 JSX 转换成某个函数嵌套调用的结构,而这个函数是可以自定义的,具体请参考 transform-react-jsx
请注意一下两点:
ok,经过 babel 转换之后,原有的 JSX 变成了下面这个样子。

从图中我们可以看到:经过 babel 转换之后,JSX 变成了 preact.h 的嵌套调用。
因此,问题就转化为:如何编写这样的一个 h 函数,使得上述嵌套调用最终返回一个层级嵌套的对象,此对象表征了 DOM 的结构。
h 函数的编写
h 是这样的一个函数,接收参数为:标签名、属性值和子元素,返回一个对象,该对象描述了一个 DOM 节点。
经过这样的 h 函数的嵌套调用,最终返回的结果如下:

DOM 渲染
有了上面的 vNode 结构,我们便能将之转换成真实的 DOM 元素。此处逻辑并不复杂,无非是递归的调用,代码如下:
最终实现效果如下图所示:

后话
本文实现的具体代码参考这里,这只是一个最基本的 demo,后续还有很多有待探索的功能,比如构造 Component 类,比如 DOM 的 diff 和 update 等等。
参考资料:WTF is JSX, By developit
--------------- EOF ----------------
The text was updated successfully, but these errors were encountered: