html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
<div id="app"></div>
<script src="./render.js"></script>
<script>
//1. 通过h函数来创建一个Vnode
const vnode = h(
"div",
{ class: "why", onClick: "(e)=>{console.log(e)}" },
[h("h2", null, "当前计数:100"), h("button", null, "+1")]
); // vdom
// console.log(vnode);

//2. 通过mount函数,将vnode挂载到div#app上
mount(vnode, document.querySelector("#app"));
</script>
</body>

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
const h = (tag, props, children) => {
// vnode -> javascript对象 -> {}
return {
tag,
props,
children,
};
};

const mount = (vnode, container) => {
//vnode -> element
// 在vnode上添加一份el真实dom
// 1.创建出真实元素,并在vnode上保留el
const el = (vnode.el = document.createElement(vnode.tag));
console.log(el);

// 2. 处理props
if (vnode.props) {
for (const key in vnode.props) {
const value = vnode.props[key];
if (key.startsWith("on")) {
el.addEventListener(key.slice(2).toLocaleLowerCase(), eval(value));
} else {
el.setAttribute(key, value);
}
}
}

//3. 处理children
if (vnode.children) {
if (typeof vnode.children === "string") {
el.textContent = vnode.children;
} else {
vnode.children.forEach((item) => {
mount(item, el);
});
}
}

container.appendChild(el);
};