-
Notifications
You must be signed in to change notification settings - Fork 19
/
React.js
84 lines (82 loc) · 3.3 KB
/
React.js
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
// 防止局部变量污染全局,只暴露全局的方法
(() => {
let rootElement, rootReactElement;
const REACT_CLASS = 'REACT_CLASS';
// React基础组件库
class Component {
constructor(props) {
this.props = props;
}
setState(state) {
// this.state = state; 导致年龄和姓名丢失
this.state = Object.assign({}, this.state, state);
reRender();
}
}
// React.createElement
function createElement(parentEle, props, ...childEles) {
if (typeof parentEle === 'function' && /^\s*class\s+/.test(parentEle.toString())) {
// (1)当为类组件时
let component = new parentEle(props);
component.type = REACT_CLASS;
return component;
} else if (typeof parentEle === 'function') {
// (2)当为函数组件时
return parentEle(props);
} else {
// (3)当为html标签组件时
let parentElement = document.createElement(parentEle);
Object.keys(props || {}).forEach(key => {
if(/^on.*$/.test(key)) {
eventName = key.slice(2).toLowerCase();
parentElement.addEventListener(eventName, props[key]);
} else if(key ==='className') {
parentElement.setAttribute('class', props[key]);
} else if(key ==='style') {
Object.keys(props[key]).forEach(attr =>
parentElement.style[attr] = props[key][attr]
);
} else if (key === 'ref'){
props[key](parentElement);
} else {
// 添加其他如href等属性直接添加进来
parentElement.setAttribute(key, props[key]);
}
});
childEles.forEach(child => {
if(typeof child === 'string') {
// (1)当子元素是一个字符时
parentElement.innerHTML += child;
} else if (Array.isArray(child)) {
// (2)当子元素是一个数组中包含多个Node节点时
child.forEach((childItem) => parentElement.appendChild(childItem));
} else if(child !== null && typeof child === 'object' && child.type === 'REACT_CLASS') {
parentElement.appendChild(child.render());
} else if(child !== null && typeof child === 'object') {
// (3)当子元素是一个Node节点是直接附加到父节点
parentElement.appendChild(child);
}
});
return parentElement;
}
}
function render(insertEle, rootEle) {
rootElement = rootEle;
rootReactElement = insertEle;
let currentEle = rootReactElement.type === 'REACT_CLASS' ? rootReactElement.render() : rootReactElement;
rootEle.appendChild(currentEle);
}
function reRender() {
while(rootElement.hasChildNodes()) {
rootElement.removeChild(rootElement.lastChild);
}
ReactDOM.render(rootReactElement, rootElement);
}
window.React = {
createElement,
Component
}
window.ReactDOM = {
render
}
})();