Skip to content

Mini Vue

结合我们前面两个章节编写的 RendererReactivity 代码,我们现在来构造一个 Mini Vue

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Mini Vue Example</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="./main.ts"></script>
  </body>
</html>
ts
import { reactive } from '../reactivity/reactive'
import { Container, VNode, h, mount, patch } from '../renderer/renderer'
import { watchEffect } from '../reactivity/watch'

const App = {
  data: reactive({
    count: 0,
  }),
  render() {
    return h(
      'div',
      {
        onClick: () => {
          this.data.count++
        },
      },
      String(this.data.count)
    )
  },
}

function mountApp(component: typeof App, container: Container) {
  let isMounted = false
  let oldVNode: VNode

  watchEffect(() => {
    const newVNode = component.render()
    if (!isMounted) {
      mount(newVNode, container)
      isMounted = true
    } else {
      patch(oldVNode, newVNode)
    }
    oldVNode = newVNode
  })
}

mountApp(App, '#app')