React的虚拟dom实现原理

虚拟DOM的渲染机制

学习React必须知道React的两个方面,一个是虚拟DOM,另一个是Diff算法。今天我们先来看一下React的虚拟DOM的实现原理。
下面是虚拟DOM的一个简单实现原理,要是想深究的话,还是需要去阅读一下相关的源码部分。

原理: React会先将你的代码转换成一个javascript对象,然后再把这个javascript对象转换成真实的DOM。而这个javascript对象就是所谓的虚拟DOM。

实现步骤:

  1. 基于babel-preset-react-app把JSX变成React.createElement(...)。可以理解为JSX只是React.createElement的语法糖。

    <div className="box" style={{color: '#f00'}} index={0}>
        123
        <p>456</p>
    </div>
    

    经过babel转换成下面的样子:

    React.createElement("div", {
            className: "box",
            style: {
                color: '#f00'
            },
            index: 0
        }, "123", React.createElement("p", null, "456")
    );
    
    • 第一项:标签名(或者函数组件、类组件)
    • 第二项:标签上的属性值(没有属性默认是null)
    • 第三项或者更多项:标签的子节点(文本节点或者元素节点-所有的元素节点都会重新走React.createElement())
  2. 执行React.createElement(...)会返回一个javascript对象,这个对象就是所谓的虚拟DOM。

    任何的创建更改都是都是对这个javascript对象进行的操作,事件监听时也是对这个javascript对象进行事件监听,会代理到原生的DOM上。

    • createElement会返回一个虚拟对象 let VitrualDomObj = React.createElement(...),通过控制台打印出来VitrualDomObj可以看见:
      react虚拟dom
    • 虚拟dom:
          {
              type:标签名或组件名
              props:{
                  className: "box",
                  index: 0,
                  style: {color: "#f00"},
                  children:子节点内容(特点:没有子节点,则没有这一项,只有文本节点的时候,是一个字符串,有多个子节点的时候是一个数组)
              }
          }
      
      实现原理:
       export function mycreateElement(type,props,...childs){
           let obj = {}
           obj.type = type;
           obj.props = props || {};
           if(childs.length > 0){
               obj.props.children = childs.length === 1 ? childs[0] : childs;
           }
           return obj;
       }
      
  3. 把这个虚拟DOM通过render函数转换成真实的DOM

    // 使用render转换成真实dom
    myrender( VitrualDomObj , document.getElementById('root'));
    

    实现原理:

    export function myrender(VitrualDomObj, container, callback) {
    
        let { type, props } = VitrualDomObj
        let element = document.createElement(type);
    
        for (let key in props){
            if(!props.hasOwnProperty(key)) return;
    
            if(key === 'className'){
                element.className = props[key];
                continue;
            }
    
            if(key === 'style'){
                let sty = props[key];
                for(let attr in sty){
                    if(!sty.hasOwnProperty(attr)) return;
                    element.style[attr] = sty[attr];
                }
                continue;
            }
    
            if(key === 'children'){
                let children = props[key];
                children = Array.isArray(children) ? children : [children];
                children.forEach((item)=>{
                    if(typeof item === 'string'){
                        element.appendChild(document.createTextNode(item))
                        return;
                    }
                    myrender(item,element);
                })
                continue;
            }
            element.setAttribute(key,props[key]);
        }
    
        container.appendChild(element);
        callback && callback();
    }
    

以上就是一个简版的虚拟dom实现原理,总结一下,总共分为三步:

  1. babel将jsx语法转成React.createElement(…)的形式。
  2. React.createElement函数将参数转换成javascript对象的形式。
  3. ReactDOM.render将javascript对象转换成真实的dom插入到指定的dom容器中。
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值