jsx本质
jsx是js的语法拓展,本质是React.createElement的语法糖。
原理
通过babel将jsx代码转为React.createElement的函数调用。步骤如下:
遇到一个标签就会转化成React.createElement('div',{class:'active'},子元素)的函数调用,把【标签类型】和【标签属性】还有【子标签】传递给这个函数,然后会生成虚拟dom树(虚拟dom作用:跨平台和性能更高,毕竟更新更少),最终react-dom生成真实dom。
虚拟dom优势
前面提到两点优势,跨平台和更新更少。
1、跨平台
生成的虚拟dom就是js对象,如果是在web平台,就可以将js对象转为以div标签的形式;如果是在安卓平台,则可以转为view控件的形式。所以虚拟dom能根据平台特性转为对应的真实形式,这也就是跨平台的能力。
2、更新更少
在一个for循环中,我们循环100次,每次对p标签中显示的数字加1,因为更新真实dom是同步的,那就真的需要更新100次。
如果我们引入了虚拟dom,在循环中,我们只需要更新100次虚拟dom,等循环结束,我们再去更新真实dom,这样更新真实dom的操作就只用1次。如果我们只关注表象,那引入虚拟dom后更新dom就是‘异步的’了。
是否还有优化空间?有的,那就是引入diff算法。引入diff算法后,在那100次更新虚拟dom的过程中,我们可以比对新旧虚拟dom的差异,再得出一个正确的虚拟dom,从而减少虚拟dom的更新。
例子
例如,有下面一段代码
const element = <h1>Hello, World!</h1>;
在编译阶段,上述JSX代码将被转换为以下形式:
const element = React.createElement("h1", null, "Hello, World!");
React.createElement()函数创建了一个React元素,它描述了一个<h1>标签,没有属性,且包含文本内容"Hello, World!"。
验证一下
babel转createElement的过程
访问babeljs.io,按下图步骤操作,就能看到babel转化后的结果,最后将jsx代码换成转化后的代码,会发现还是能显示。
替换
虚拟dom在哪
前面提到过,createElement方法的返回值就是虚拟dom,那我们可以直接打印,打印结果如下:
总结
react对于模板的解析主要借助了babel然后做dom转化,而vue则是靠vue自己的代码进行转化(毕竟vue还有一些指令) 。当然vue也支持jsx,解析流程也和react类似。