Skip to content

Generic v-on syntax without argument #4703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Akryum opened this issue Jan 12, 2017 · 6 comments
Closed

Generic v-on syntax without argument #4703

Akryum opened this issue Jan 12, 2017 · 6 comments

Comments

@Akryum
Copy link
Member

Akryum commented Jan 12, 2017

This special syntax is somewhat inspired by the v-bind:class.

Let's take this component as an example:

<template>
  <test />
</template>

<script>
export default {
  methods: {
    handleEvents (type, ...args) {
      console.log('event=' + type, ...args)
    },
    handleAction (...args) {
      console.log('action!', ...args)
    },
  }
}
</script>

These call the handleEvents method when any event is emitted, with the following signature: function (eventType, ...args).

<test v-on="handleEvents" />
<test v-on="'handleEvents'" />
<test v-on="[handleEvents]" />
<test v-on="['handleEvents']" />

These call both handleEvents and handleEvents2 methods.

<test v-on="[handleEvents, handleEvents2]" />
<test v-on="['handleEvents', 'handleEvents2']" />

These call the handleAction method when the action event is emitted, with the usual signature: function (...args).

<test v-on="{ action: handleAction }" />
<test v-on="{ action: 'handleAction' }" />

You can mix everything!

<test v-on="[handleEvents, { action: handleAction }]" />

Or store it all in a reactive property!

<template>
  <test v-on="handlers" />
</template>

<script>
export default {
  data: {
    handlers: ['handleEvents', {action: 'handleAction'}],
  },
  methods: {
    handleEvents (type, ...args) { ... },
    handleAction (...args) { ... },
  }
}
</script>

With the $props, it could allow making specialized components out of generic ones much easier:

<template>
  <ui-modal v-bind="$props" v-on="$emit">
    <input :value="value" :placeholder="placeholder" />
  </ui-modal>
</template>

<script>
import Modal from 'components/Modal.vue'

export default {
  name: 'ui-input-modal',

  props: {
    ...Modal.props,
    value: {},
    placeholder: String,
  },
}
</script>

In this example, we expose the same interface as the Modal component (props and events), while making it more specialized with news props/events and a pre-made template.

If you want, take a look at this working proof of concept.

@LinusBorg
Copy link
Member

Really like this!!

@yyx990803
Copy link
Member

Hmm, I feel this introduces way too much syntax variations for the same purpose, and the only benefits is that it becomes a bit more flexible to deal with programmatic event handling in templates. However, imo when you need this level of flexibility for attaching event handlers, it'd be better off to just use a render function rather than adding new syntax to the templates.

@Akryum
Copy link
Member Author

Akryum commented Jan 22, 2017

We could only have the v-on="handler" syntax to support "extending" templates. How would you implement the InputModal in the example?

@yyx990803
Copy link
Member

It can be done in render function as:

render (h) {
  return h('modal', this.$vnode.data, [
    h('input', ...)
  ])
}

this.$vnode is the VNode representing this component in the parent's tree. You can directly pass its data to the other component, which makes the other component inherit all props / event listeners.

@Akryum
Copy link
Member Author

Akryum commented Jan 23, 2017

And in JSX I would do return <Modal { ...this.$vnode.data }>?

@yyx990803
Copy link
Member

Yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants