Mithril.js: Allow space-separated attrs to bind one function to multiple events / lifecycle hooks

Created on 18 Dec 2018  Â·  6Comments  Â·  Source: MithrilJS/mithril.js

Description

Instead of

const handler = e => {}
const hook = v => {}

m('div', {
  onclick: handler,
  onkeypress: handler,

  oncreate: hook,
  onupdate: hook,
})

Allow

m('div', {
  'onclick onkeypress' : e => {},

  'oncreate onupdate': v => {},
})

Why

  1. Increase expressivity, reducing the need for statements and increasing declarative power for scenarios when the same handler applies to multiple triggers
  2. Reduce the cognitive burden of scope issues
  3. Allow ad-hoc React-hooks-like flexibility with fully functional single-scope components

Possible Implementation & Open Questions

  1. Handler code forking can be handled via event.type interpolation. To enable lifecycle forking, a vnode.phase flag could achieve similar functionality.

Is this something you're interested in working on?

Yes

Most helpful comment

Hi @barneycarroll, thank you for submitting an issue related to the question I asked in Gitter. That's very kind and proactive of you.

@fuzetsu provided a userland solution to my problem which I'll transcribe here in case it helps someone else:

const multiEvent = (events, handler) =>
events.split(',').reduce((o, e) => Object.assign(o, { [e]: handler }), {})

m.mount(document.body, {
view: () => m('button', {
    ...multiEvent('onclick,oncontextmenu,onmouseover', e => {
    e.preventDefault()
    console.log(e.type)
    })
}, 'Button')
})

Also provided a working demo.

I'm quite inexperienced with Mithril so, for what is worth, my uneducated opinion is that binding a single function to multiple events might not be too common and I'd consider supporting it only if performance and code complexity impact were very low.

Regardless, I'm impressed with Mithril and its community so far. The context of this very issue demonstrates a very welcoming environment.

All 6 comments

BTW, I have major performance concerns here, particularly if it involves components' lifecycle methods, too.

Yeah that makes me feel uneasy too. Is it the cost of querying every key for whitespace or the overhead of iteration on each match in particular?

It's the overhead of matching and inability to cache them. Also, there's
overhead in splitting and iterating the events, and the open question of
whether this extends to attributes as well (like "checked data-checked": checked), which itself is a mild perf headache because of the complex
parsing it'd entail.
On Tue, Dec 18, 2018 at 18:12 Barney Carroll notifications@github.com
wrote:

Yeah that makes me feel uneasy too. Is it the cost of querying every key
for whitespace or the overhead of iteration on each match in particular?

—
You are receiving this because you commented.

Reply to this email directly, view it on GitHub
https://github.com/MithrilJS/mithril.js/issues/2343#issuecomment-448406981,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AERrBAplw2z-IABZ1R3Z5N2Dchjn7gVQks5u6XZYgaJpZM4ZZOvp
.

Hi @barneycarroll, thank you for submitting an issue related to the question I asked in Gitter. That's very kind and proactive of you.

@fuzetsu provided a userland solution to my problem which I'll transcribe here in case it helps someone else:

const multiEvent = (events, handler) =>
events.split(',').reduce((o, e) => Object.assign(o, { [e]: handler }), {})

m.mount(document.body, {
view: () => m('button', {
    ...multiEvent('onclick,oncontextmenu,onmouseover', e => {
    e.preventDefault()
    console.log(e.type)
    })
}, 'Button')
})

Also provided a working demo.

I'm quite inexperienced with Mithril so, for what is worth, my uneducated opinion is that binding a single function to multiple events might not be too common and I'd consider supporting it only if performance and code complexity impact were very low.

Regardless, I'm impressed with Mithril and its community so far. The context of this very issue demonstrates a very welcoming environment.

@ww9 all suggestions are always welcome! Thanks for participating — it's our collective exploration of possibilities that makes Mithril what it is.

@barneycarroll

[Me:] It's the overhead of matching and inability to cache them. Also, there's
overhead in splitting and iterating the events, and the open question of
whether this extends to attributes as well (like "checked data-checked": checked), which itself is a mild perf headache because of the complex
parsing it'd entail.

Remove the "inability to cache them" part. I thought about this part again and realized caching isn't as bad as I initially thought. I still have concerns about how high the overhead is for the dictionary access, and I'll need to iterate the string to ensure there's no spaces for the fast case where I don't have to cache.

I'm thinking this can be done separately for DOM vnodes (in render/hyperscript.js) and for components (in render/render.js), so we don't have to muck up the core renderer too much.

Edit: that quoted comment was from me.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ozgurrgul picture ozgurrgul  Â·  3Comments

hadihammurabi picture hadihammurabi  Â·  4Comments

josephys picture josephys  Â·  4Comments

designMoreWeb picture designMoreWeb  Â·  4Comments

pygy picture pygy  Â·  4Comments