序
最近由于工作需要,写了一个类似React.js的框架,目前支持绝大部份React.js的API接口,开发使用上与原生的React.js无异,唯一的差异是我的框架原生支持IE7,支持双向数据绑定等,在这个过程中,踩了很多坑,也从更深层次的了解了React.js,个人感觉收获很大,所以就想写一写文章分享一下整个过程,希望对想了解React.js的同学们有所帮助,也希望大家在阅读的过程中,提出一些指正的想法,谢谢
引言
近些年,前端技术的发展十分火爆,各种各样的技术层出不穷,React.js、Vue.js、Angular.js等,在技术飞速发展的同时,还引入了工程化、模块化、组件化等前端管理思路。本着结合新技术和新模式进行前端改造建设,提升前端团队的技术水平及产品质量,在对比各种技术的优缺点后(具体的比较可以查看本公众号之前发表的一篇文章React.js VS Vue.js),决定使用React.js作为前端团队的基础开发框架。
知彼知已
在我们热热闹闹的开发出第一个基于React.js的组件版本后,在与业务讨论技术落地的细节的时候,业务要求前端页面要兼容IE7,可是React天生不支持兼容IE7,IE8都是旧版本加上垫片程序才可以支持,15版本后的新版本官方直接不支持IE8了,显然我犯了一个致命的错误(长记性了),就是没有仔细了解历史存量问题----页面要支持IE7。摆在我面前只有两条路,一是解决React.js兼容IE7的问题,二是认怂,换另外一种兼容IE7的技术(据了解,目前只有knockout.js支持IE系列比较好)。
一是技术上我不轻易认怂,二是好不容易培养起来团队的React.js开发技术不用了可惜,所以没得选择,只能翻过兼容IE7这座大山了(正如所有前端人员心中一定会有这样一句话,万恶的IE)。在仔细啃了一下React.js的源码后,发现React.js里面很多对象的监听用到了Object.defineProperty这个方法,IE8原生支持一部分的功能,还可以通过垫片库的方式,IE7压根就不支持这种方式(臣妾做不到啊)!!!当然这只是其中的一个问题,IE7下还有其他的莫名其妙的问题,难道我们要根据这些问题逐一解决?这显然是不现实的!也不知哪根筋抽了,突然间脑子里闪过这样一个想法,“自己写个解析引擎?”那就这么吧。
在动手之前,要先了解一下“对手”,知彼知已,百战不殆。首先,我们先看一看React.js的运行态。
通过上图,我们可以看出,理论上,前面的开发态和编译态,我们可以借助已有的工具像Webpack和Babel,支持我们开发人员继续使用JSX语言和ES6语法进行开发,只需针对运行态对编译后的原生JS脚本进行解析渲染,并且使用原生的解决方案来兼容IE7。这样子的解决方案,前端团队成员不用做出什么技术调整,可复用原来的React.js的脚手架和开发技术,既解决复用团队技术,又能解决兼容IE7的问题,十分完美。
在分析完总体的,我们来看看开发态和运行态的详细情况,首先,我们来看看开发态时写的JSX脚本,这个JSX脚本无法直接在浏览器中运行,需要进行编译转换才可以。
我们再看看编译后的原生JS脚本,在经过脚手架工具类的编译后,上面的JSX脚本变成了可以在浏览器里正常运行的原生JS脚本。
所以,我们要自己写解析引擎,就是要让上图的代码能正常的加载运行起来。
构建引擎
1.最小单元法分析
通过上面编译后的JS脚本,我们可以分析得出,要想让上面的代码正常运行起来,我们至少需要有React和ReactDOM这两个对象,而对于React对象,必须有createClass和createElement的方法,其中,createClass的入参是一个直接量对象,必须有render方法,createElement方法的入参是可变的,并且可以嵌套调用。
同样的道理,我们分析ReactDOM对象,只有render方法,入参有两个(实际上ReactDOM.render是可以支持三个入参的,最后一个入参是加载完成后的回调函数,后面会提到)。第一个参数为React.createElement返回的对象,第二个参数为将渲染的目标容器的DOM对象。
分析好关系后,开始动手写引擎。
2.创建引擎
2.1创建引擎基础骨架
2.2补充肌肉
这样子就完成了解析引擎的初步构建,将上面的代码放入一起运行,可以见到正常的运行结果。
页面源码:
运行结果:
自己创建一个解析引擎是不是很简单?然而,这才只是刚刚开始,要完善框架,前面还有很多很多的功能需要处理,例如props,refs,compnentDidMount,state等机制的支持,将会在后面这一系列文章中逐步完善,今天先写到这,欲知后事如何,请听下回分解。