Open lukeed opened 6 years ago
Of course, @
could still be used for any native handler assignment. It just would not compile down to a direct x.on___
assignment.
// <div :onclick="foo" />
div.onclick = foo;
// <div @click="foo" />
div.addEventListener('click', foo);
Don't the brackets signify that an attribute is dynamic? The parser can see here that class
is fixed but disabled
isn't:
<button class="large" disabled={inactive}>click me</button>
Another aside, I think passing functions should work like JSX. It passes a reference when uninitialized, or you may pass along initial values that set up a new functional return value
I think this is something that HTMLx itself shouldn't have an opinion on — the parser just expects a valid JavaScript expression, and it's up to the framework itself to interpret the expression in a particular way. I'm firmly convinced that the ergonomics of the Svelte approach are better 😀 (if counterintuitive at first, especially for people coming from a React background), but it's definitely something that reasonable people can disagree on.
Not sure I totally understood the part about :onfoo
/on:foo
vs @foo
? It's probably worth noting though that custom elements will often invent their own custom events, which blurs the line a bit between native DOM events and component-specific ones.
Don't the brackets signify that an attribute is dynamic?
Yes, but you have to parse the value to determine if it is, rather than the attribute name directly. It's an extra two steps.
Not sure I totally understood the part about
:onfoo/on:foo
vs@foo
?
This is basically just @
being an alias for x.addEventListener('foo')
which covers both custom and native elements, while :onfoo
maps to x.onfoo
, which is limited to native events only. IMO there should be an ability to choose either approach.
It's an extra two steps.
Hmm — I haven't found it burdensome in the context of Svelte's parser. In any case I reckon it's ok to add complexity to the parser if it makes the developer's experience nicer.
This is basically just
@
being an alias forx.addEventListener('foo')
Ah, interesting. I have to admit I never ever use div.onclick
and friends, I always use addEventListener
, so I didn't see that distinction at first. Is there an advantage to using things like onclick
?
No worries!
It's just another way to add & remove event listeners. (It's also more compact, ignoring any on()
helpers after n-repeats.) The idea here is that since onclick
and friends are native attributes, I should be able to assign a listener that way when I want to, since it's no different than something like :disabled
(or disabled={}
).
I'm on the fence about losing on:
since that is descriptive, minimal character count, and helps n00bs know immediately what they're seeing.
Understandable! 👍 I'm still on the other side, and found that it was really easy to get used to in Vue.
@lukeed thank you for putting this RFC together, it's great to see this kind of discussion :)
I'm a long time Vue user but I actually found Svelte's syntax refreshing as it more closely resembles regular HTML. The simplicity is a big win in my opinion.
Would multiple ways to handle events keep that simplicity? I'm not against having both but since assignment to on*
with native events (e.g. onclick
) is rare, should we have syntax support? Developers can still set up such a handler during the component/app life cycle, albeit with extra effort. On the flip side, having these event handlers in the template itself is better for clarity of event driven logic.
Back to the original topic of prefixes, I'm in favour of on:foo
over :onfoo
because, at least in Svelte, it aligns with the other directives — e.g bind:*
, ref:*
, use:*
, transition:*
, in:*
, out:*
. Isn't :transitionfoo
harder to read?
@MaxMilton No problem, thanks!
I'm a user & fan of both 😄 And, working a lot with Preact, I do actually write onclick={}
99% of the time. Immediate/direct access to the DOM in Preact is a feature IMO, not a bug as some will call it.
I've thought about this some more — it's been a while. So long as I can write to any HTMLElement attribute, then I'm satisfied. Eg, if I can write onclick=
in the same way I can write to disabled=
, great!
The point I was trying to make is that something like on:*
or transition:*
is awesome, but it should 100% signify that whatever you're doing is tied to a specialized, framework-specific thing & not the DOM equivalent.
For example:
<div onclick={ onNative } />
<div onclick={ this.onNative } />
<div on:click={ this.onSpecial } />
///
function onNative(ev) {
console.log('DOM Element:', this);
console.log('~> same as:', ev.target);
// ...
}
// borrowing Vue/Svelte definition here
export default {
methods: {
// mount the same handler
onNative,
onSpecial(ev) {
// whatever preprocessing XYZ does for you
// eg, this can be React's custom event system
console.log('Component instance:', this);
console.log('~> target:', ev.target);
}
}
}
The native handler(s) would be untouched, nothing special added to them. Using the library/framework's eventing system/modifiers/etc would only kick in behind a on:*
namespaced assignment.
Yes, the special appearance of :
should indicate something framework-y.
Yo~!
I wonder if it'd be easier to parse & filter down to dynamic attributes via a common prefix match. In this case, "easier" is meant to cover the dev declarations and parser's workload. This is purely because of the consistent syntax & ability (on the parser) side to lazily infer if work will need to be done on X attribute later on.
Like stated in readme, any combination (or lack thereof) of
"
and{}
is valid, as that doesn't really matter and essentially is like a semicolons-in-js debate. They're stylistic & will be required for compiler clarification in few cases.Another aside, I think passing functions should work like JSX. It passes a reference when uninitialized, or you may pass along initial values that set up a new functional return value. I can be swayed on this 😇
Custom Directives
Lastly, that leaves custom directives. This will borrow a lot from Vue & from Svelte's
on:*
, of course, but the difference here is that the syntax change illustrates a completely custom handler rather than attempting to write into a native attribute or event handler.The parser then has a really easy time figure out if something is meant to be static or dynamic. Essentially it's just this: