Profile picture of Marc Backes (very handsome) Profile picture of Marc Backes (very handsome)
Marc Backes

Build An App With Your Own Mini-Vue

May 23, 2020 · by Marc Backes
Profile picture of Marc Backes (very handsome) Profile picture of Marc Backes (very handsome)
Build An App With Your Own Mini-Vue Build An App With Your Own Mini-Vue

This post is the fifth part of a series called Create Your Own Vue.js From Scratch, where I teach you how to create the fundamentals of a reactive framework such as Vue.js. To follow this blog post, I suggest you first read the other parts of the series.


In the last posts, we created our own virtual DOM and replicated a rudimentary Vue 2 reactivity.

For the virtual DOM, we created an engine that allows us to create virtual nodes, mount/unmount them to/from the actual DOM. The code can be found on Github.

For the reactivity, we built a dependency class, which we then use to detect changes in object property changes, we bound using Object.definePropert(). The code can be found on Github.


First, we create a new HTML-file add a div with the ID app, and <script> tag.

Second, we copy the following functions from the VDOM example into the <script></script>-tag:

  • h
  • mount
  • unmount
  • patch

Third, we copy the following elements from the reactivity example into the <script>-tag:

  • Dep-class
  • watchEffect-function
  • reactive-function
  • activeEffect variable declaration

Writing our template

Let's assume we want to create a very simple click-counter like this one:


We would need a structure like this:

<div id="app">
  <div id="container">

The #app-div is the mounting point for our application, so we just need to create a template for the .clickContainer and it's content. For this, we write a function that returns the template we will render to the DOM later, using the h-function from the VDOM:

function render(clickCount) {
  return h(
    { class: 'container' },
    [h('h1', null, clickCount)],
    h('p', null, 'clicks'),

Create our reactive state

In this simple example, we only have one variable, so one property in our reactive state:

const state = reactive({
  count: 0,

Make our VDOM reactive

We're almost done. What we need to do now is to call the watchEffect function, so we can react upon changes in the state.count property. There are two scenarios for this:

  1. It's the first time our callback function gets called: We need to mount the template to the DOM
  2. It's not the first time our callback function gets called: We need to patch() the node in the DOM

To differentiate between this, let's create a variable previousNode.

let previousVnode
watchEffect(() => {
  if (!previousVnode) {
    // No previous node. We must mount it to the DOM
  } else {
    // There is a previous node. We need to patch it (update)

For the first case, we create a new node with our render function and mount it to the DOM:

previousVnode = render(String(state.count))
mount(previousVnode, document.getElementById('app'))

For the second case, we create a new node and patch it to the previousNode. (Compare and see what the differences are).

const newVnode = render(String(state.count))
patch(previousVnode, newVnode)
previousVnode = newVnode

Create the click event

Our reactive DOM is now done. It will react to changes to the state.count variable. The last thing left for our counter to work is to increment the counter on the click of the #app element:

We just add onclick="state.count++" to it:

<div id="app" onclick="state.count++">

And voilà! We have a simple click counter, we built on top of our own reactive library.

Congratulations! 🎉

Add some style

This of course still looks ugly. To make it a little bit fancier, add a <style>-tag to the top of the document and add the following CSS code to it:

* {
  user-select: none;
body {
  margin: 0;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
#app {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #41b883;
  color: #ffffff;

h1 {
  font-size: 10rem;
  font-weight: 900;
  margin: 0;

p {
  margin: 0;
  text-align: center;
  font-weight: 100;
  font-size: 3rem;


This is a very simple example, and could be done with way less code in simple JavaScript. However, keep in mind that this series is for educational purposes, so you get an insight to the internals of a frontend framework. It's not meant for you to create your own framework and use it in production. (Of course, you could.)

In this last part (for now), there we learned how to put together our own reactivity with our own virtual DOM to create a rudimentary reactive frontend framework. If you are keen to build more stuff on top of this, go ahead. You'll learn a lot in the process. If you built something, let me know and I'll check it out. Curious if someone uses this to learn stuff.

There might be a bonus coming some day where I build something more advanced with this "framework".

The code of this last part can be found on Github as well.