Vue: Generic v-on syntax without argument

Created on 12 Jan 2017  路  6Comments  路  Source: vuejs/vue

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.

feature request

Most helpful comment

Yes.

All 6 comments

Really like this!!

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.

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

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.

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

Yes.

Was this page helpful?
0 / 5 - 0 ratings