querySelector/ID component design
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 1.3k
- Forks
- 46
- PR merge metrics
- No merged PRs in 30d
Description
So I've been experimenting a lot with life cycles and yoyo components. So far the most reliable component design I've found is to use randomly generated or pre-assigned ID's, querySelection and the MutationObserver.
Here is an example component:
const Component = function (_yield) {
var id = "id" + parseInt(Math.random()*1000000)
var open = true
function onload () {
console.log(id + "loaded!")
}
function onupdate () {
console.log(id + "mutated")
}
function onunload () {
console.log(id + "unloaded!")
}
function toggle () {
open = !open;
yo.update(document.querySelector("#"+id), render(_yield))
}
function render (_yield) {
return yo`
<div id=${id}>
${id}
<button onclick=${toggle}>Toggle</button>
<span> ${open && yo`<div> It's Open </div>` || yo`<div> It's Closed </div>`}</span>
<hr />
${_yield}
</div>
`
}
onmutation(id, onload, onunload, onupdate)
return render(_yield)
}
My reusable MutationObserver which tracks when the component loads, unloads and updates:
var watch = []
if (window && window.MutationObserver) {
var observer = new MutationObserver(function (mutations) {
for(var i = 0; i < watch.length; i++) {
var selector = document.querySelector(watch[i][0]);
if(selector && !watch[i][4]) {
watch[i][4] = 1
watch[i][1](watch[i])
}else if(!selector && watch[i][4]) {
watch[i][2](watch[i])
watch.splice(i, 1)
}
}
for (var i = 0; i < mutations.length; i++) {
var mutation = mutations[i]
for(var i = 0; i < watch.length; i++)
if(watch[i][0].substr(1) == mutation.target.id) watch[i][3](watch[i])
}
})
observer.observe(document.body, {childList: true, subtree: true})
}
function onmutation (el, l, u, m) {
l = l || function () {}
u = u || function () {}
m = m || function () {}
watch.push([(el[0] != "#" && "#" + el || el), l, u, m, 0])
}
-- 335 bytes min+gz
I believe this to be the most reliable way to make stand alone components that update themselves.
Central Reason: if your component internally selects a node and not an ID, the dom can be morphed from above, altering the selected node, without changing the original node target in the component. The component then becomes useless, as its event methods are targeting a dom node that no longer exists. I ran into this problem constantly when I was using yo.update on higher level components, which didn't update the node targets of the morphed lower level components.
Using ID's and querySelecting seems to be the most reliable, light-weight and simple solution to this problem. This MutationObserver pattern is similar to @shama's on-load, but it uses querySelecting and not an actual dom node.
I didn't find the morphdom-hooks to be reliable either, as they would look for a dom node target that would sometimes not exist. This is because higher level hooks dont walk the dom lower and update component targets below. Diablo is a system that does this. However, it follows the react pattern fairly heavily, and I couldn't get it running without issues. I'm not huge on a react knock off either for my components.
Would love to get thoughts on this design and a name for my querySelector mutationobserver =D?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the component example and the MutationObserver implementation in the issue body. The issue asks for feedback and a name for the design, but it names no repository file, test, entry point, or concrete acceptance criteria, so a definition of done is not established.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100