Make Reactive DOM Elements With Just Native JavaScript
For a while have I wondered how some JS libraies, such as Vue or React make DOM reactive. And by the way, tha DOM being reactive to data change is probably one of the reasons why Vue or React has become famous in the first place.
How does Vue or React make DOM reactice to data change? I don't know. Though, I have tried to read their source code, but failed to understand the mechanism.
So I tried to make my own DOM reactive system.
Playground
Sample Code
<div>
<span data-data="message1"></span>
<span data-data="message1"></span>
<button onclick="addfunc1()">+</button><br>
<span data-data="message2"></span>
<span data-data="message2"></span>
<button onclick="addfunc2()">+</button>
</div>
<script>
var data = {
message1:0,
message2:0
};
//Define data.
var key = Object.keys(data);
//Get object "data" key such as "message1" and "message2" and put them in an object.
function addfunc1(){
data.message1 ++;
updatefunc('message1');
};
function addfunc2(){
data.message2 ++;
updatefunc('message2');
};
//Define functions that change data.
function updatefunc(n){
document.querySelectorAll('[data-data='+n+']').forEach(function(x){
x.innerHTML = data[n];
});
};
//Define functions that make DOM react to data change.
function init(){
keyj.forEach(function(x){
document.querySelectorAll('[data-data='+x+']').forEach(function(y){
y.innerHTML = data[x];
});
})
};
init();
//Load all data to the DOM in the beginning.
</script>
What if I want to Manipulate Data?
var data = {
message1:0,
message2:0,
message3:0,
message4:0,
get message5(){
return this.message3 + this.message4;
}
};
var key = Object.keys(data);
function addfunc1(){
data.message1 ++;
updatefunc('message1');
};
function addfunc2(){
data.message2 ++;
updatefunc('message2');
};
function addfunc3(){
data.message3 ++;
updatefunc('message3');updatefunc('message5');
};
function addfunc4(){
data.message4 ++;
updatefunc('message4');updatefunc('message5');
};
function updatefunc(){
document.querySelectorAll('[data-data='+n+']').forEach(function(x){
x.innerHTML = data[n];
});
};
function init(){
keyj.forEach(function(x){
document.querySelectorAll('[data-data='+x+']').forEach(function(y){
y.innerHTML = data[x];
});
})
};
init();
Key Points
- The above app is reactice to data change. When data change, DOM changes. The reactive mechanism is based on the updatefunc().
- In this app, only DOM with data change will be updated, since the updatefunc function calls only those span with relevant data-data value.
- Of course, one can modify the above code to make all DOM updated with any data change, which would make this app run slower with O(n), runtime grows linearly with the number of data instead of O(1), constant runtime regardless of the number of data.
- document.querySelectorAll returns a node list that suppost array moethod "forEach".
- document.getElementsByClassName would return a node list that does not support array method, unless wrap it in Array.from(some nodelist).
- When I need to manipulate data. I need to call "updatefunc" everytime the manipulated data is involved.
- Object getter in javascript can has a key which can collected by Object.keys() method.
Comments
Post a Comment