Skip to content

Instantly share code, notes, and snippets.

@netcall-jlo
Created January 30, 2024 09:45
Show Gist options
  • Save netcall-jlo/771f418083dbddc58068a54e0e990fbd to your computer and use it in GitHub Desktop.
Save netcall-jlo/771f418083dbddc58068a54e0e990fbd to your computer and use it in GitHub Desktop.
A quick demonstration of responsive JavaScript - based on a video whose URL I no longer remember
<!doctype html>
<html lang="en-GB">
<head>
<title>Testing reactivity</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,width=device-width">
</head>
<body>
<p>Count: <span id="count"></span></p>
<p><button id="count-increase">count + 1</button></p>
<p>Offset: <span id="offset"></span>; Total = <span id="total"></span></p>
<p><button id="offset-increase">offset + 1</button></p>
<script>
var me = (function () {
const me = {};
const globalData = new WeakMap();
function getSubscribersForProperty(target, key) {
if (!globalData.has(target)) {
globalData.set(target, new Map());
}
const map = globalData.get(target);
if (!map.has(key)) {
map.set(key, new Set());
}
return map.get(key);
}
let activeEffect;
function track(target, key) {
if (activeEffect) {
const effects = getSubscribersForProperty(target, key);
effects.add(activeEffect);
}
};
function trigger(target, key) {
const effects = getSubscribersForProperty(target, key);
effects.forEach((effect) => effect());
};
me.reactive = (object) => new Proxy(object, {
get(target, key) {
track(target, key);
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key);
}
});
me.ref = (value) => {
const refObject = {
get value() {
track(refObject, "value");
return value;
},
set value(newValue) {
value = newValue;
trigger(refObject, "value");
}
};
return refObject;
};
me.whenDepsChange = (update) => {
const effect = () => {
activeEffect = effect;
update();
activeEffect = null;
};
effect();
};
me.calculate = (process) => {
const ref = me.ref();
me.whenDepsChange(() => {
ref.value = process();
});
return ref;
};
return me;
}());
</script>
<script>
const {
ref,
whenDepsChange,
calculate
} = me;
const count = ref(0);
const offset = ref(0);
const total = calculate(() => count.value + offset.value);
whenDepsChange(() => {
document.getElementById("count").textContent = count.value;
document.getElementById("offset").textContent = offset.value;
document.getElementById("total").textContent = total.value;
});
document.getElementById("count-increase").addEventListener("click", () => {
count.value += 1;
});
document.getElementById("offset-increase").addEventListener("click", () => {
offset.value += 1;
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment