在index.js中引用这个即可
class Element {
constructor(type, prop, children) {
// 把这些私有变量 存储到实例上 方便后面的函数调用
this.type = type
this.prop = prop
this.children = children
}
fn(str) {
return str.replace(/[A-Z]/g, function (a) {
return "-" + a.toLowerCase()
})
}
render() {
let ele = document.createElement(this.type)
// 把prop中的行内属性 放到这个标签上
for (let k in this.prop) {
// for in 循环的特点:他会把你自己在原型上增加的属性也循环出来
if (this.prop.hasOwnProperty(k)) {
// 若 k 是 className -> class
// htmlFor -> for
// style -> 变成对象
// ele.setAttribute(k, this.prop[k])
switch (k) {
case "className":
ele.setAttribute("class", this.prop[k])
break;
case "htmlFor":
ele.setAttribute("for", this.prop[k])
break;
case "style":
// this.prop[k] 是一个对象 我们需要把对象拼接成字符串
let str = ""
Object.keys(this.prop[k]).forEach(key => {
// key 有可能是驼峰命名的属性 需要我们转成 -
str += `${this.fn(key)}:${this.prop[k][key]};`
})
ele.setAttribute(k, str)
break;
default: ele.setAttribute(k, this.prop[k])
break;
}
}
}
this.children.forEach(item => {
// item 有可能是字符串 还有可能是Element实例
// 若是字符串 我么需要使用 createTextNode(字符串) 转成节点
// 若是 Element 实例 我们需要使用 实例.render() 的返回结果
item instanceof Element ? ele.appendChild(item.render()) : ele.appendChild(document.createTextNode(item))
});
return ele
}
}
let React = {
createElement(type, prop, ...children) {
// let children = [].slice.call(arguments, 2)
// type 标签名
// prop 行内属性
// 第三个参数及以后 都是当前标签的子节点 我们用一个数组包起来
return new Element(type, prop, children)
}
}
let ReactDOM = {
render(ele, container) {
// ele是 Element 的实例
container.appendChild(ele.render())
}
}
// 不再引入 React 和 ReactDOM 自己造
// let ele = <h1>清欢</h1>
let ele = React.createElement("h1", { className: "qqq" }, "长安故里", React.createElement("span", { style: { color: "red", fontSize: "12px" } }, "清欢"))
// 以上两种写法是一个效果,只是在react中第一种写法被Babel转化成了第二种
ReactDOM.render(ele, document.querySelector("#root"))