Open Gyanreyer opened 1 year ago
All you need to create a scope are braces, no need for IIFE.
So, maybe to simplify your idea, all that needs to be done is have the webc:scoped use a unique id generator for the component instance. And "binding" should maybe be automatic within webc:scoped.
Then have the following:
{ this = document.getElementById(uniqueElementId);
[user scoped code goes here]
}
So, this would refer to the web component. But that means the component element needs to be kept on the page (webc:nokeep would be no bueno here) I suppose a compile error can pop up if webc:nokeep is used with script webc:scoped.
I hadn't realized that IE11 supports block scopes even though it doesn't support all ES6 features, so yeah that's probably fine.
I like having a distinction between normal scopes and "bound" scoped scripts to enable writing shared setup code (like initializing an IntersectionObserver) which doesn't need to be duplicated across every instance of the component. There are other ways to get around that, but it feels like it wouldn't be as big of an improvement over how things work right now as it could be.
Also for what it's worth, if you have a ton of instances of a component on a page, having an individual code block for each one seems like it could balloon very quickly, hence why I proposed encapsulating the bound code in a single re-usable function which we can then call with each instance of the component element.
Hello! Sorry to drop a massive proposal on you, if it's too much or there's a better way to submit things like this, I'm happy to move it elsewhere!
So I've been building lots of little sites with WebC and it just keeps getting better and better, thanks for the amazing work! I know Adding More JavaScript To Your Page is generally not a priority considering what Eleventy is going for, but I wanted to share some thoughts I've been having regarding writing scripts for WebC components and how I feel like the DX could potentially be improved.
The problem
Sometimes, I want to write a script in a component file which provides some enhancements to all of the instances of that component, ie setting up an IntersectionObserver which triggers an animation on the element(s) when scrolled into view. Doing so looks something like this:
Overall, these are obviously not massive problems as I have found workarounds for them which aren't too bad, but it feels like it could be improved.
Proposed change 1: Allow setting
webc:scoped
on<script>
tagsScoped script tags will be bundled into a scoped IIFE like in my example above, providing a way to keep your component-specific logic scoped instead of being intermingled with all of the other bundled scripts on the page.
builds to...
Like with scoped styles, you could provide a value to
webc:scoped
which represents an ID for the scoped function. Separate scripts with the same scope will be bundled together into the same function.builds to...
Like with styles, an unnamed scope should produce a random scope id which is unique to the component. Custom-named scopes can potentially collide if two separate components have scripts which use the same scoped id.
Note: I went with an anonymous
function
over an arrow function in an effort to maximize browser support.Proposed change 2: Add a new
webc:bind
attribute for scoped scriptsThis is where the fun really starts! Building on scoped scripts, you could also allow scripts to be bound to instances of the component element. The script's contents would be bundled into a function which is invoked once for each instance of the element and bound to that instance, so you may access it via
this
.This would be incredibly useful for setup tasks like adding event listeners, observing elements with IntersectionObserver, etc.
In order to facilitate this, we will need to apply a scoped class to the element in the same way that
webc:scoped
works for styles. If a value is provided towebc:scoped
, that value will be added as a class on the element. If no value is provided, we will generate one that is unique to the component; ideally, this would be the exact same unique class that is used for scoped styles.builds to...
If your component has a mix of bound and unbound scoped scripts, the unbound ones should be placed first. This would allow you to perform setup for shared variables/logic that you want to be available to each bound script.
builds to...
I think this would be incredibly helpful and take WebC components a step even closer to matching the benefits of a native web component. Of course, I'm not married to anything in this proposal and I understand that it would be relatively complex to implement. In fact, I could very easily be overlooking some reasons why this might not even be possible or make sense! But if any portions of it do sound interesting, then I would love to help make it a reality!