-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
154 lines (147 loc) · 3.84 KB
/
index.html
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
</body>
<script>
function createApp(rootComponent) {
return {
mount(rootContainer) {
render(rootComponent, rootContainer)
},
}
}
function render(rootComponent, rootContainer) {
patch(rootComponent, rootContainer)
}
function patch(vnode, container) {
const { type, props, children } = vnode
if (typeof type === "string") {
// element
const el = document.createElement(type)
// props
if (typeof props === "object") {
for (const key in props) {
el.setAttribute(key, props[key])
}
}
// children
if (Array.isArray(children)) {
children.forEach((child) => {
patch(child, el)
})
} else {
patch(children, el)
}
container.appendChild(el)
} else if (typeof vnode === "object") {
// component
const { setup, render } = vnode
const componentInstance = {
vnode: null,
}
// initSetupState
const setupResult = setup()
if (typeof setupResult === "object") {
componentInstance.setupState = setupResult
} else if (typeof setupResult === "function") {
// render函数
componentInstance.render = setupResult
}
// 处理render
if (componentInstance.render) {
componentInstance.vnode = componentInstance.render()
} else {
componentInstance.vnode = render.call(componentInstance.setupState)
}
patch(componentInstance.vnode, container)
} else if (typeof vnode === "string") {
// children is only one
container.textContent = vnode
}
}
function h(type, props, children) {
return {
type,
props,
children,
}
}
const targetStack = new WeakMap()
let activeEffct = () => {
console.log("effect")
}
function reactive(raw) {
return new Proxy(raw, {
get(target, key) {
const result = Reflect.get(target, key)
track(target, key)
return result
},
set(target, key, value) {
const result = Reflect.set(target, key, value)
trigger(target, key)
return result
},
})
}
function track(target, key) {
if (!activeEffct) return
let depMap = targetStack.get(target)
if (!depMap) {
depMap = new Map()
targetStack.set(target, depMap)
}
let dep = depMap.get(key)
if (!dep) {
dep = new Set()
depMap.set(key, dep)
}
dep.add(activeEffct)
}
function trigger(target, key) {
let depMap = targetStack.get(target)
if (!depMap) return
let dep = depMap.get(key)
if (!dep) return
dep.forEach((effect) => {
effect()
})
}
function effect(fn) {
activeEffct = fn
fn()
activeEffct = null
}
const user = reactive({
name: "张三",
})
effect(() => {
console.log("username", user.name)
})
const App = {
// setup() {
// return {
// msg: "一条消息",
// }
// },
setup() {
const msg = "hello Setup!!!"
return () => {
return h("div", { class: "setupRender" }, msg)
}
},
render() {
// return h("div", {}, this.msg)
return h("div", {}, ["Hello Vue3!!!", h("p", {}, this.msg)])
},
}
createApp(App).mount(document.querySelector("#app"))
</script>
</html>