react jsx渲染原理分析

jsx的使用

let data=123;
ReactDOM.render(<div>
            <h2>hello</h2>
            <p>{data}</p>
            <Child/>
        </div>,
        document.querySelector("#root")
  • 注意事项
    1. {}
      中括号中可以放js表达式
      不能放对象(会报错),数组中的项也不能是对象
      可以放函数,但函数执行需要有返回值(否则报错)
    
    1. 循环绑定
    let arr=['a','b','c','d']
    ReactDOM.render(<ul>
    {
      arr.map((item,index)=>{//如果{}中是个函数的话 函数执行必须要有返回值,否则会报错。
        return <li key={index}>{item}</li>
      })
    }
    </ul>,root)
    
    let arr=[<div>hello</div>,<div>world</div>,<p>haha</p>]
    ReactDOM.render(<ul>
    {=arr}
    </ul>,root)
    
    1. 判断(需要使用三元运算符)
     let data={show:true};
     ReactDOM.render(<div>{data.show?123:''}</div>,root)
    
    1. className代替class
    ReactDOM.render(<div className={class1}>123</div>,root)
    
    1. style
    ReactDOM.render(<div style={{color:red}}>123</div>,root)
    
    or
    let style1={color:red}
    ReactDOM.render(<div style={style1}>123</div>,root)
    
    5.只能有一个顶级元素
    jsx语法中只能有一个顶级标签(元素)这和react的diff算法相关
    
    1. false,null,undefined,和 true 都是有效的的 children(子元素) 。但是并不会被渲染,下面的JSX表达式渲染效果是相同的,都是空
    <div />
      <div></div>
      <div>{false}</div>
      <div>{null}</div>
      <div>{undefined}</div>
      <div>{true}</div>
    </div>
    
    1. label的for属性用htmlFor代替
    ReactDOM.render(<label htmlFor="name" ></label>,root)
    

jsx的编译过程

  1. 有 JSX 的地方,在文件开头就需要引入 React,因为实际上 JSX 是使用了 React.createElement,JSX 只是一个JS 的语法糖,所以需要引入 React 包,否则会报错。
  2. react-dom 是一个把React 代码渲染到网页端的包,主要利用了render函数。
  • 示例:babel编译jsx
ReactDom.render(<ul className="list">
   <li className="item">a</li>
   <li className="item">b</li>
 </ul>,root)
//转化为
createElement('ul',{className:'item'},[
    createElement('li',{class:'item'},['a']),
    createElement('li',{class:'item'},['b']),
])
  • createElement函数的实现
    createElement执行会把jsx转化成为一个虚拟DOM,就是一个对象
vertualDom <==>
{
  type:'ul',
  props:{class:'list',children:[
      {
          type:'li',
          props:{class:'item',children:'a'},
           key:null,
           ref:null
      },
      {
          type:'li',
          props:{class:'item',children:'b'},
           key:null,
           ref:null
      },
  ]},
  key:null,
  ref:null
}

实现

//函数接受三个参数type,props,children,产出一个虚拟DOM对象
//如果props中有ref或key,就把ref或key放到外边,props中的ref或key为undefined,否则外边的ref或key为null;
//如果有childs,就把childs放到props的children上,如果childs只有一个,就是一个字符串,否租就是一个数组
function createElement(type,props,...childs){
    props=props||{}
    let ref=null,key=null;
    if(ref in props){
        ref=props.ref;
        props.ref=undefined;
    }else{
        ref=null;
    }
    if(key in props){
        key =props.key ;
        props.key =undefined;
    }else{
        key =null;
    }
    let obj={
      type,
      props:{
        ...props,
        //如果没有childs就是"",如果有一项就是一个字符串,如果有多项就是一个数组
        children:childs.length<=1?(childs[0]||''):childs
      },
      key,
      ref,
    }
  return obj;
}
  • render函数的实现
    render将createElement中传出的虚拟DOM转化为真实的DOM,挂载到页面上
//函数传入虚拟DOM,容器和执行结束后的回调函数
function render(objJSX,container,callback){
    let {type,props}=objJSX;
    let  newElement=document.createElement(type);
    for(let attr in props){
      let value=props[attr];
      if(props.hasOwnProperty(attr))break;
      if(typeof value=='undefined')break;
      if(attr.startsWith('on')){//事件处理
        let attch=attr.slice(2).toLowerCase();
        newElement.addEventListener(attch,value,false);
        continue;
      }
      switch(attr.toUpperCase){
        case 'CLASSNAME'://class特殊处理
          newElement.className=value;
          break;
        case 'STYLE'://style特殊处理
          for(let st in attr){
            newElement.style[st]=attr[st]
          }
          break;
        case 'CHILDREN'://children特殊处理
          !value intenceof Array?value =[value ]:null;//不是数组变成数组
          value.forEach((item)=>{
            if(typeof item=='string'){//是个字符串,直接插入
               newElement.appendChild(document.createTextNode(item))
            }else{//是一个对象,递归调用
              render(item,newElement)
            }
          })
          break;
        default://普通属性
        newElement.setAttribute(attr,value);
      }
    }
    container.appendChild(newElement);
    callback&&callback();
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,607评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,239评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,960评论 0 355
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,750评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,764评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,604评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,347评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,253评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,702评论 1 315
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,893评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,015评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,734评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,352评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,934评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,052评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,216评论 3 371
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,969评论 2 355

推荐阅读更多精彩内容

  • 原教程内容详见精益 React 学习指南,这只是我在学习过程中的一些阅读笔记,个人觉得该教程讲解深入浅出,比目前大...
    leonaxiong阅读 2,838评论 1 18
  • 40、React 什么是React?React 是一个用于构建用户界面的框架(采用的是MVC模式):集中处理VIE...
    萌妹撒阅读 1,017评论 0 1
  • 以下内容是我在学习和研究React时,对React的特性、重点和注意事项的提取、精练和总结,可以做为React特性...
    科研者阅读 8,233评论 2 21
  • 原文地址:Learning React.js is easier than you think原文作者:Samer...
    sunshine小小倩阅读 4,229评论 3 41
  • 一、安装环境之前,检查是否已经安装过或者系统是否自带jdk环境 查看CentOS自带JDK是否已安装。 ◆输入:y...
    devstrongzhao阅读 384评论 0 0