The issues with Abell Components #126
Replies: 1 comment 1 reply
-
Hi! Disclaimer: I'm a complete noob in abell, so this might be way off, feel free to simply ignore it! I have 2 points here:
1. I think the javascript needs to be scoped on the instance level, not component levelTake this example of rending a list of Users: <!-- index.abell -->
{{
const User = require('./User.abell');
const users = ['saurabhdaware', 'siddharthkp'];
}}
<body>
<main>
<section>
Users:
<ul>
{{
users.map(user => <User props={handle: user} />)
}}
</ul>
</section>
</main>
</body> In this component, some information is already available because it's passed down in props. The rest isn't urgent and can be lazily loaded through an API <AbellComponent>
<template>
<li>
<img />
<span id="handle">{{props.handle}}</span>
<span id="joined-on"></span>
</li>
</template>
<style>
li {display: flex; padding: 10px;}
img { width: 20px; border-radius: 50%; margin: 0 10px;}
</style>
<script>
const handle = scopedSelector('#handle').innerText
// fetching this part on the client, it's not urgent info
fetch('https://api.github.com/users/' + handle)
.then(response => response.json())
.then(data => {
console.log(handle, data.avatar_url)
scopedSelector('img').src = data.avatar_url
scopedSelector('#joined-on').innerText = ', joined on ' + data.created_at
});
</script>
</AbellComponent> This is the rendered result, only one of the rows has the additional info. As you already mentioned, this happens because the logic wouldn't repeat over the different component instances and that's why it's important that the javascript for each of these is scoped to the instance level to make their own data requests and dom manipulations. From a data loading point of view, this might not be the smartest way and it would be nice to group these requests in some way, but that's necessarily in our control, like here, fetching from an external API. So, for me, this is definitely the right direction. But, of course, it comes with it's own problems
2. Lightweight instances (in bundlesize)One of the ways you mentioned to ensure scoping is duplication, this increases the bundlesize linearly which isn't too bad but not ideal. Initiating a new instances of the same component should have no additional cost. A possible solution could be to give each instance it's own key and wrap the script in a function that is called once for every instance of the component. (I'm making a bunch of assumptions on how the rendered works based on one reading of the code, I might be waaay off) <!-- Part 1: Component instances with their own hashed key -->
<section>
Users:
<ul>
<li data-abell-compo-1-instance-1>
<img data-abell-compo-1-instance-1>
<span id="handle" data-abell-compo-1-instance-1>saurabhdaware</span>
<span id="joined-on" data-abell-compo-1-instance-1></span>
</li>
<li data-abell-compo-1-instance-2>
<img data-abell-compo-1-instance-2>
<span id="handle" data-abell-compo-1-instance-2>siddharthkp</span>
<span id="joined-on" data-abell-compo-1-instance-2></span>
</li>
</ul>
</section>
<!-- Part 2: defining the function from the component once -->
<script>
const mountUser = key => {
const handle = document.querySelector('#handle' + '[' + key + ']').innerText
// fetching this part on the client, it's not urgent info
fetch('https://api.github.com/users/' + handle)
.then(response => response.json())
.then(data => {
console.log(handle, data.avatar_url)
document.querySelector('img' + '[' + key + ']').src = data.avatar_url
document.querySelector('#joined-on' + '[' + key + ']').innerText = ', joined on ' + data.created_at
});
}
</script>
<!-- Part 3: calling the function for each component instance -->
<script>
mountUser('data-abell-compo-1-instance-1')
mountUser('data-abell-compo-1-instance-2')
</script> Hope that makes sense! Once again, I have no idea if this is useful or fits the implementation details of the renderer, so feel free to ignore all of it! |
Beta Was this translation helpful? Give feedback.
-
Component Instance Mess
Think of this scenario,
index.abell
This is how
Nav.abell
looks likeNow in the
Nav.abell
code, it looks like that it is going to change the innerHTML of span from Test to yoo. However, since the<Nav />
is called twice, it creates two spans but in bundle, we only bundle one javascript file. So thedocument.querySelector
will not be able to select the second element.This is output of above code:
Solution:
<Test />
(currently it is scoped per component (not instance)But this will mean, we generate two statements of
document.querySelector
. So if the code if 500 lines, it will generate 1000 lines of code.document.querySelectorAll
and handle such cases (too hard and hacky to implement)^^ A similar issue will happen if we use
<Nav />
inindex.abell
and inside a sub-component that is imported inindex.abell
Beta Was this translation helpful? Give feedback.
All reactions