• React的Render的简单实现


    createElement然后遍历children属性,完成整个dom的创建,其实是相当耗费性能的,react之所以能实现高性能,是因为它实现了局部dom的更新,而不是像我们_render方法里面那么简单粗暴。 更新优化算法diff

    ReactDOM.render(
        

    Hello, world!

    ,    document.getElementById('root') );

    实际上是JSX进过转换是这样的

    ReactDOM.render(
        React.createElement( 'h1', null, 'Hello, world!' ),
        document.getElementById('root')
    );

    render方法的作用就是将对象转换成虚拟DOM,再最终渲染成真实的DOM

    function render( vnode, container ) {
        
        // 当vnode为字符串时,渲染结果是一段文本 // 1. 判断节点类型
        if ( typeof vnode === 'string' ) {
            const textNode = document.createTextNode( vnode );
            return container.appendChild( textNode ); // 2. 给真实节点返回该类型的节点
        }
    ​
        const dom = document.createElement( vnode.tag );  // 3. 获取要创建节点的标签名
    ​
        if ( vnode.attrs ) { // 4. 判断是否有attr属性,有则遍历attr属性给每个设置属性
            Object.keys( vnode.attrs ).forEach( key => {
                const value = vnode.attrs[ key ];
                 setAttribute( dom, key, value );    // 设置属性
            } );
        }
    ​
        vnode.children.forEach( child => render( child, dom ) );    // 5. 递归渲染子节点
    ​
        return container.appendChild( dom );    // 6. 将渲染结果挂载到真正的DOM上
    }

    还有setAttribute方法:

    function setAttribute( dom, name, value ) {
        // 如果属性名是className,则改回class
        if ( name === 'className' ) name = 'class';
    ​
        // 如果属性名是onXXX,则是一个事件监听方法
        if ( /on\w+/.test( name ) ) {
            name = name.toLowerCase();
            dom[ name ] = value || '';
        // 如果属性名是style,则更新style对象
        } else if ( name === 'style' ) {
            if ( !value || typeof value === 'string' ) {
                dom.style.cssText = value || '';
            } else if ( value && typeof value === 'object' ) {
                for ( let name in value ) {
                    // 可以通过style={ width: 20 }这种形式来设置样式,可以省略掉单位px
                    dom.style[ name ] = typeof value[ name ] === 'number' ? value[ name ] + 'px' : value[ name ];
                }
            }
        // 普通属性则直接更新属性
        } else {
            if ( name in dom ) {
                dom[ name ] = value || '';
            }
            if ( value ) {
                dom.setAttribute( name, value );
            } else {
                dom.removeAttribute( name );
            }
        }
    }

    每次render前,清理一下之前的内容:

    const ReactDOM = {
        render: ( vnode, container ) => {
            container.innerHTML = '';
            return render( vnode, container );
        }
    }

    在index.html里面增加容器:

  • 相关阅读:
    chatgpt——链式思考(CoT)提示工程训练
    关于jar包的一些思考
    java 企业工程管理系统软件源码 自主研发 工程行业适用
    Redis中的原子操作(2)-redis中使用Lua脚本保证命令原子性
    cocos游戏引擎制作的滚动框地图防止误点操作的简单方法
    Databend JSON 复杂数据类型的设计与使用 | Databend 特性系列
    网上最全的套接字socket
    node_modules/XXX/index.js:XXX;XX ||= XXX?.[level];SyntaxError: Une
    使用Xshell远程连接虚拟机的linux
    【计算机组成原理】备考必刷大题
  • 原文地址:https://blog.csdn.net/m0_60297110/article/details/127765837