I gave a live-coding talk last week at the Manchester Web Meetup #4. I built a virtual DOM from scratch in less than an hour during the talk. I...
For further actions, you may consider blocking this person and/or reporting abuse
This is the kind of article that makes me feel so Lucky to be alive at this moment and be part of this code side of the world which is filled with extremely passionate and knowledgeable people who really make efforts to share their knowledge with others.
It's because of engineers like you that it's actually approachable to not only learn to code, but learn to make amazing things.
Forgive me for saying so much, I just happen to really appreciate this, even if I'm not thinking of building a Vdom right now.. Knowing how things work behind the wheel feels very good.
Thank you.
It's because of readers like you that make me feel motivated to keep writing! Your comment almost made me teared 😭! Thank you so much!!!! ♥️♥️♥️
Thank you! Awesome article again!
I love your comment!
Hey, really great write up. I missed the talk at Manchester Web Meetup, but wanted to see this talk, when I first learned React a few years I looked at how the Virtual DOM was put together and did a similar createElement/mount function pair, but I think the real power on the Virtual DOM, especially when used in React is the diffing mechanism. I didnt attempt that at the time, but I think what you have put above is great because I think it helps show why/how frameworks like React update themselves in reaction to changes and you do it with understandable and clean code, awesome :D
Thank you so much! Writing clean and elegant code is my passion. I tried to keep things clean so that people can understand it.
I'm the same, I think there is a lot to be gained from clean code, not just for yourself, but for other developers that do (or will) work with it too :) Doing it in example/tutorial code even more so as it improves the value and quality of the article, like you have here :)
I am so glad I found someone who appreciate this. ❤❤
Last whole week i am researching about reactive, and virtual dom to make my hobby javascript library. I am stacking around creating virtual dom and diffing. I saw your post
and it help me alot. I'm really thank you for your explanation and i saw you in video and you're so active in that and full of energy. And again Thank you :)
Sure. You have stepped into the common trap of thinking recursion recursively. Your brain will stack-overflow first before the computer does haha.
The reason why you are so confused is because you are lacking the "leap of faith" for recursion. You try to figure out what is happening, then you look into the function; it calls itself, and u look into the function again... Then you are lost.
All you need is faith!
The first thing is to define what
diff
anddiffChildren
do. I made it very clear fordiff
.So the idea is, you know
diff
will somehow call itself again at some point. And when this happens, all you need is the "leap of faith"; believe thatdiff
will work as you wish! Don't look intodiff
again to try to figure things out! Just think about whatdiff
should do and return. By our definition, it will return apatch
! So just assume the recursive calls todiff
will work and read on.Teaching recursion using this example is a bit hard, have a look at this article which I explained very clearly how you could obtain faith in recursion.
The leap of faith takes some practice to get use to it. If you want some exercise, I am happy to give you some challenge and guide you through them. Feel free to DM me on twitter: @ycmjason
thank you very much for such a simplified explanation and elegant code. I have been wanting to understand how vuejs virtual dom works.
Then i recreated your idea i was mind blown by the patch($node) function i was first confuse by how this functions know exactly which element to update on the actual DOM, until i when through the zip function over and over before i understood it.
I have currently implemented it in typescript added reactiveness, event listener.
Once again thank you some much, its individuals like you that make coding magical yet understandable 🤩
Thank you for your kind words. ❤️
Thank you so much for your kind words! I am very very glad to see you enjoying the post!
This is one of the main reasons why I did this topic!! I am glad this presentation achieved its goal!
Please ask the questions! Would be nice if I can clear things further!
Very good job. Thank you for a thorough guide!
Actually, there is a typo in your code within the post.
Inside the function that we put into
additionalPatches
we shouldrender
not thenewVChildren
but theadditionalVChild
.This code appears in the first example in the explanation of
diffChildren
function.You are a hero! Thanks for pointing that out! 🎉🎉🎉 I'll change it as soon as possible!
This typo is still in the article 😉
Great content. I am wondering why you don't use Proxy objects instead of this complex diff function.
Because Proxy wasn't ready at the time of writing this article. How do you think Proxy can be used here to improve this?
You can create a proxy object out of a regular object, then you can listen to any change to the object and execute some code against those changes : javascript.info/proxy
Thank you for the wonderful guide
Hey! This article is gold (:
I didn't even notice the time pass while reading! I will follow u to check your contents! Well done my friend :D
Is it '0 to oldVChildren.length' or should that be '0 to oldVChildren.length-1'?
nice catch! I will update!
Hi,
Thanks a lot for the article, very nicely explained.
How would you recommend to handle events on the virtual nodes (e.g. add a addEventListener on a node that will influence another node rendering)?
since many people asked. i might write an eps 2 that could cover this.
Please do, if you haven't already. I enjoyed your article btw, pinned on reading list.
Currently, I have the following somewhat working:
render.ts
if (events) {
events.map(([type, event]) => {
$element.addEventListener(type, event)
})
}
index.ts
attrs: {...},
events: [['click',() => {console.log('event handled')}]]
It seems to work and not to propagate upwards. Not sure about dynamically rendering nested elements or w/e. Thoughts?
Couldn’t agree more with this comment. I looked into Reacts vdom a while back to better understand and I just got lost and lost. This post was first time I’d seen someone breakdown concisely and in a way that doesn’t overwhelm the reader with “frivolous” complexities
Well done thanks, Jason!
Amazing. I did go through the whole and implemented it myself also.
Can I ask for an article or video or both on a similar topic - "Create your own bindings using proxies from scratch".
It was originally requested in the comments of the YouTube video.
bindings as in reactivity?
Yes. Reactivity in Vue (how DOM updates and render the changes, how changes are detected, etc).
Also how
computed properties
andwatchers
work.I would love to see your take on this.
The version with
does not work correctly if child nodes are removed, since live NodeList (
$parent.childNodes
) updates the collection automatically when the DOM changes (e.g. child is removed). Hence,forEach
is not called for all (original) elements (child nodes). For example, if there are 3 child nodes and the first patch keeps the child and the second and third patch delete the child, then only the first and second patches are called. The third patch is not called, since the second patch removes the node, which removes it from$parent.childNodes
.It is fixed by the version that uses
zip
, since it copies the elements of$parent.childNodes
into anArray
, which is not automatically updated when the DOM changes.I could attend to the talk and it was perfect. I really appreciate and value the ability to share knowledge on such an interesting and cutting-edge topic as this. Thanks mate ;)
❤❤❤ thank you so much!!!!
share the post if you liked it! spread the knowledge! :)
I am sorry that my explanation didn't help. :(
diff
has two base cases:undefined
In fact, all my base cases are defined in a guard clause. This means that all the return statement before the last return can be considered as base case.
Oops, I just realised there is one more, which is when there is no children in the node. But I didn't explicitly deal with that case as it will be automatically dealt with in the for loop in
diffChildren
Yes. Totally based on the leap of faith. It always work! It's the very important thing you need when dealing with recursion.
Well, merge sort and quick sort if written in a recursive way, can be reasoned about using the "leap of faith" for sure. Whether or not the original Author has the leap of faith there is noway to find out. 😂😂
Leap of faith will definitely work in professional and interview problems. It's just a mindset you should have when writing recursive solutions, not really a method. Once you do more recursion, you will become confident enough to hold that faith all time.
The linked CodeSandbox examples don't run. I get
It seems that a differnt index.html is used in the sandbox. Hence, the target element
#app
to mount to is not foundThank you very much for the article and video. Great explanation from scratch. I noticed that the GIF animation does not play till the end. Every time count changes, the animation is reset, although the image DOM element is not changed. Does anyone know the reason?
really appreciate your sharing, I want to translate this article to Chinese and share to other people in China, I wonder if you agree me to do that, thank you so much。
That's a great idea. As long as you credit me, feel free! Please let me proof read before you post it! :)
Halfway through the article but you are real genius .Great contribution .
Thank you!!! Thanks for taking the time to read through this. This is a very very long article I know. Should have made this a series of articles really haha.
Any way to get in touch with you Jason .Would love to learn things from you .
Just feel free to DM me on twitter. @ycmjason
Found this, will spend my weekends to go through this for sure, thank you.
Thank you for this
The video was awesome. I am glad you record it.
Awesome energy and super clear, thanks for sharing.
Congratz bro! 🚀
Thank you!
the way too awesome article I have ever seen about programming 😍
Bless you too Linus!
I've created a to-do app using this simple virtual DOM but I've got problems that the code does not handle deletion and reordering of real DOM element's