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裏邊



複製代碼
相關文章
相關標籤/搜索