React JSX原理

function fn(str) {

    //把驼峰转成横杠的函数
    return str.replace(/[A-Z]/g,function(a){
        return '-' + a.toLowerCase()
    })
  }



class Element{
    //本身声明一个元素类

    constructor(type,props,children){
        //咱们把这三个参数赋成私有属性
        this.type = type;
        this.props = props;
        this.children = children;
    }

    render(){
        //把传进来的内容转成DOM

        //根据元素类型创造一个元素 
        //根据元素类型 创造一个元素
        let ele  = document.createElement(this.type);


        //2.把props中的属性设置成元素的行内属性
        for(let k in this.props){
            if(this.props.hasOwnProperty(k)){
                //this.props的私有属性
                //稍微对className和htmlFor作一下处理 style

                switch (k) {
                    case 'className':
                        ele.setAttribute('class',this.props[k])
                        break;
                    
                    case 'htmlFor':
                        ele.setAttribute('for',this.props[k])

                        break;

                    case 'style':
                        //循环style对应的对象; 而后拼接字符串
                        //在给元素设置行内样式
                        let str = '';
                        for(let val in this.props[k]){
                            //正常须要判断一下 是不是私有属性
                            //还须要把驼峰转成横杠
                            if(this.props[k].hasOwnProperty(val)){
                                str += `${fn(val)} : ${this.props[k][val]}`
                            }
                        }

                        ele.setAttribute(k,str)
                        break;


                
                    default:ele.setAttribute(k,this.props[k])
                        break;
                }
                ele.setAttribute(k,this.props[k])
            }
        }

        //第三部 处理children
        //children 要不就是文本 要不就是一个新的结构
        //怎么查看是不是新结构? 咱们instanceof

       this.children.forEach(item => {
            //如果一个新结构 则咱们调用render方法转成真实DOM
            //不然直接建立一个新的文本节点
            item instanceof Element ? ele.appendChild(item.render()):ele.appendChild(document.createTextNode(item))
        });

        return ele; //返回值必须是咱们创造的这个元素
    }
}

let React = {
    createElement(type,props,...children){
        //该函数的第一个参数 是标签类型
        //第二个参数是行内属性
        //从第三个及之后都属于该标签的内容部分 因此咱们使用剩余运算符接收
        return new Element(type,props,children)
        //返回是一个类的实例
        //也就是在append时 咱们须要给的是一个真实的渲染过的DOM
    }
}


let ReactDOM = {
    render(ele,container){

        //ele是一个虚拟DOM 添加到元素内部的应该是一个真实DOM    
        //因此这里咱们 append 进去的应该是处理过的ele
        container.appendChild(ele.render())
    }
}



let ele = React.createElement('div',
{id:'zf'},
'你好',
React.createElement('h4',{style:{color:'red',fontSize:'50px'}},'哈哈',React.createElement('span',null,'666')),
React.createElement('h2',{className:'box'},'哈哈'),
React.createElement('h3',null,'哈哈'),
'你好',
)


ReactDOM.render(ele,document.getElementById('root'))//结果是把ele添加到root里边



复制代码
相关文章
相关标签/搜索