babel对jsx的解析以及react虚拟dom树的加载转换

一、babel是提供对react jsx语法的支持

我们可以像以前一样脚本中引入babel的js包,实现浏览器对这种jsx的支持,默认的babel碰到jsx这种语法时候,会调用React里的API进行处理,下边示例中,我们没有引入React,则会报错。

这也是为什么 我们使用import导入react包的时候,名字必须为React。

babel对jsx的解析以及react虚拟dom树的加载转换_第1张图片

2、稍微做一些改动,我们可以自定义对jsx的渲染,指令是:/** @jsx hyperScript **/,定义一个自己的jsx渲染器,其中hyperScript 表示方法名字。告诉babel在解析碰到jsx时候该如何做?

下面,我们书写这个方法。在jsx中,我们认为每一个虚拟DOM其实就是一个json文件。例如

,就会等价于

{ nodeName :"div" , attrbutes : { id : "name"} , children : []  }。下面我们的hyperScript就会长这样

function hyperScript(nodeName , attributes , ...args){

    //返回虚拟DOM, 虚拟DOM结构,用[].concat(...args) 连接所有子节点,返回构建完成的JSON。

    let children =  args.length ? [].concat(...args) : [];
    return {nodeName,attributes,children  }
}

从下图中可以看出,引入script标签时候的type指定为babel,会在浏览器启动页面时候转换为内置的babel代码

babel对jsx的解析以及react虚拟dom树的加载转换_第2张图片

jsx在解析后,参数如下图黑线标记的

babel对jsx的解析以及react虚拟dom树的加载转换_第3张图片

3、显然react使用jsx写完的组件,最终被解析为了虚拟的json对象树,如下图:

babel对jsx的解析以及react虚拟dom树的加载转换_第4张图片

我们只要把这个虚拟树渲染到真实的dom下就可以了,需要一个render函数,也就是ReactDOM.render函数的功能,这里我们自己定义一个,如下:

本质上就是将虚拟DOM映射成 DOM节点 
        function render( vnode ){
            //如果是文本,直接返回
            if(vnode.split){
                return document.createTextNode( vnode )
            }
            //是一个虚拟DOM
            let node = document.createElement( vnode.nodeName );
            //get属性
            let attrs = vnode.attrbutes || {} ;
            //给节点加上属性
            Object.keys( attrs ).forEach( item => node.setAttribute( item , attrs[item] ) );
            //递归处理子元素,children
            ( vnode.children || [] ).forEach( item => node.appendChild( render(item) ) );
            //返回node 
            return node;
        }

4、将返回的真实的dom对象,使用jquery放置到对应的div下即可

babel对jsx的解析以及react虚拟dom树的加载转换_第5张图片

二、附上html源代码测试

https://github.com/longyangzz/react-jsx-virtualDom




  
    

    
    
  
  
    
1234556

 

你可能感兴趣的:(前端)