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裏邊
複製代碼