Created
January 30, 2024 09:45
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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