Have you ever asked yourself how a framework works?
Then Vue.js came out, and upon analyzing how it works under the hood, I was encouraged to try writing my own two-way binding system.
How does reactivity work?
It would be good to start with an understanding of how reactivity works. The good news is that this is simple. Actually, when you declare a new component in Vue.js, the framework will proxify each property (getters and setters) using the proxy design pattern.
Thus it will be able to detect property value changes both from code and user inputs.
What the proxy design pattern looks like
The idea behind the proxy pattern is simply to overload access to an object. An analogy in real life could be the access to your bank account.
For example, you can’t directly access your bank account balance and change the value according to your needs. It is necessary for you to ask someone that has this permission, in this case, your bank.
In the example above, when using the
bank object to access the
account balance, the getter function is overloaded, and it always returns
9,000,000 instead of the property value, even if the property doesn’t exist.
By overloading the
set function, it’s possible to manipulate its behavior. You can change the value to set, update another property instead, or even not do anything at all.
To keep it simple, we’ll mimic the AngularJS syntax to do it. Declaring a controller and binding template elements to controller properties is quite straightforward.
First, define a controller with properties. Then use this controller in a template. Finally, use the
ng-bind attribute to enable double-binding with the element value.
Parse template and instantiate the controller
To have properties to bind, we need to get a place (aka controller) to declare those properties. Thus, it is necessary to define a controller and introduce it to our framework.
During the controller declaration, the framework will look for elements that have
If it fits with one of the declared controllers, it will create a new instance of this controller. This controller instance is only responsible for this particular piece of template.
Here is what the handmade
controllers variable declaration looks like. The
controllers object contains all controllers declared within the framework by calling
For each controller, a
factory function is saved to instantiate a new controller when needed. The framework also stores each of the new instances of the same controller used in the template.
Looking for bindings
At this point, we’ve got an instance of the controller and a piece of template using this instance.
The next step is to look for elements with bindings which use controller properties.
Quite simple, it stores all bindings of an object (used as a hash map). This variable contains all the properties to bind with the current value and all DOM elements which bind this property.
Double bind controller properties
After the preliminary work has been done by the framework, now comes the interesting part: double-binding.
It involves binding the controller property to the DOM elements to update the DOM whenever the code updates the property value.
Also, don’t forget to bind the DOM elements to the controller property. This way, when the user changes the input value, it’ll update the controller property. Then it will also update all other elements bound to this property.
Detect updates from code with a proxy
As explained above, Vue wraps components within a proxy to react to property changes. Let’s do the same by proxying the setter only for controller bound properties.
Whenever a bound property is set, the proxy will check all elements bound to this property. Then it will update them with the new value.
In this example, we support only input elements binding, because only the
value attribute is set.
React to element events
The last thing to do is reacting to user interactions. DOM elements trigger events when they detect a value change.
Listen to those events and update the bound property with the new value from the event. All other elements bound to the same property will update automatically thanks to the proxy.
Once you put everything together, you get handmade double-bound inputs. Here is a working demo including all the code.
Congratulations! You’ve developed popular features such as custom HTML element attributes, reactivity, and double-binding!
If you found this article useful, please click on the 👏 button a few times to make others find the article and to show your support! 👊
Don’t forget to follow me to get notified of my upcoming articles 🙏
Check out my Other Posts
➥ React for beginners
- A Quick Guide to Learn React and How its Virtual DOM Works
- How to Bring Reactivity into React with States