Skip to content

Commit a209e40

Browse files
committed
chore: manually mount
1 parent b041ea0 commit a209e40

File tree

3 files changed

+102
-2
lines changed

3 files changed

+102
-2
lines changed

demo/mount.html renamed to demo/22-manually-mount.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
.red {
33
color: red;
44
}
5+
li {
6+
cursor: pointer;
7+
}
58
</style>
69
<body></body>
710
<script>
@@ -11,7 +14,7 @@
1114
props,
1215
children,
1316
}
14-
}
17+
}
1518

1619
function render() {
1720
return h('ul', {

public/vnode-to-dom.excalidraw.png

32.7 KB
Loading

slides.md

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2165,7 +2165,104 @@ function compileToFunction(template) {
21652165

21662166
## 挂载&更新
21672167

2168-
前面我们实现了 **响应式系统****编译**(丐中丐版),现在我们将它们整合起来,同时为了能将代码跑起来,我们还需要稍微简单实现下 **挂载和更新** (这里不涉及 patch)。
2168+
前面我们实现了 **响应式系统****编译**(丐中丐版),已经有能力将模板编译成渲染函数了,现在我们将它们整合起来,同时为了能将代码跑起来,我们还需要稍微简单实现下 **挂载和更新** (这里不涉及 patch)。
2169+
2170+
过程如下图所示:
2171+
2172+
<img src="/public/vnode-to-dom.excalidraw.png" />
2173+
2174+
---
2175+
2176+
对于下面的模板:
2177+
2178+
```html
2179+
<ul class="red">
2180+
<li>Vue</li>
2181+
<li>React</li>
2182+
<li>Angular</li>
2183+
</ul>
2184+
```
2185+
2186+
经过编译后,其对应的渲染函数和VNode分别如下:
2187+
2188+
<div grid="~ cols-2 gap-2">
2189+
2190+
```js
2191+
function render() {
2192+
return h('ul', {
2193+
class: 'red',
2194+
onClick() {
2195+
console.log('click')
2196+
}
2197+
},
2198+
[
2199+
h('li', null, 'Vue'),
2200+
h('li', null, 'React'),
2201+
h('li', null, 'Angular')
2202+
]
2203+
)
2204+
}
2205+
```
2206+
2207+
```js
2208+
// VNode
2209+
{
2210+
tag: 'ul',
2211+
props: {
2212+
class: 'red',
2213+
onClick() {
2214+
console.log('click')
2215+
}
2216+
},
2217+
children: [
2218+
{ tag: 'li', children: 'Vue' },
2219+
{ tag: 'li', children: 'React' },
2220+
{ tag: 'li', children: 'Angular' },
2221+
]
2222+
}
2223+
```
2224+
2225+
</div>
2226+
2227+
---
2228+
2229+
渲染函数的执行会生成虚拟 DOM,接下来我们尝试手动将虚拟 DOM 渲染到页面上。
2230+
2231+
<div grid="~ cols-2 gap-2">
2232+
2233+
```js
2234+
function mount(vnode, container) {
2235+
const el = document.createElement(vnode.tag)
2236+
if (vnode.props) {
2237+
for (let key in vnode.props) {
2238+
if (key.startsWith('on')) { // 处理事件绑定
2239+
const eventName = key.slice(2).toLowerCase()
2240+
el.addEventListener(eventName, vnode.props[key])
2241+
} else {
2242+
el.setAttribute(key, vnode.props[key])
2243+
}
2244+
}
2245+
}
2246+
if (Array.isArray(vnode.children)) {
2247+
vnode.children.forEach(child => {
2248+
mount(child, el)
2249+
})
2250+
} else {
2251+
el.textContent = vnode.children
2252+
}
2253+
container.appendChild(el)
2254+
}
2255+
```
2256+
2257+
```js
2258+
// demo: 22-manually-mount.html
2259+
2260+
const vnode = render()
2261+
console.log(vnode);
2262+
mount(vnode, document.body)
2263+
```
2264+
2265+
</div>
21692266

21702267
---
21712268

0 commit comments

Comments
 (0)