React 编译渲染原理实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
class React {
constructor() {
};


static createElement(type, options, ...arg) {
options = options || {};
// arg 储存的是剩下的参数集合,没有的话就是空数组

let obj = {type, key: null, ref: null, props: {}};

['key', 'ref'].forEach(item => {
if (item in options) {
obj[item] = options[item];
delete options[item]
}
});

obj.props = {...options};
let len = arg.length;
switch (len) {
case 0:
// 没有子节点,没有children
break;
case 1:
// 只有一个子节点,children 不是一个数组
obj.props.children = arg[0];
break;
default:
// 多个子节点
obj.props.children = JSON.parse(JSON.stringify(arg))
}

return obj
}
}

class ReactDOM {
static handChild(children, newEle) {
if (typeof children === 'object') {
// children 是一个虚拟dom
ReactDOM.render(children, newEle)
} else {
// children 是一个字符串
newEle.appendChild(document.createTextNode(children))
}
}

static render(objJSX, container, cb) {
let {type, props} = objJSX,
newEle = document.createElement(type);
for (let key in props) {
if (!props.hasOwnProperty(key)) continue;

if (key === 'children') {
let children = props['children'];
if (children instanceof Array) {
// children 是数组
children.forEach(itemChild => {
ReactDOM.handChild(itemChild, newEle)
});
continue
}
// 只有一个子节点
ReactDOM.handChild();
continue;
}

// class
if (key === 'className') {
newEle.setAttribute('class', props['className']);
continue;
}

// style 把props中的style的值依次遍历,并设置给元素
if (key === 'style') {
for (let key in props['style']) {
if (!props['style'].hasOwnProperty(key)) continue;
newEle.style[key] = props['style'][key]
}
}

newEle.setAttribute(key, props[key])
}
container.appendChild(newEle);
cb && cb()
}
}

React.createElement('div', undefined);
styleObj = {color: 'red'};