Vue: [feature] v-emit / v-call - the missing link

Created on 10 Apr 2016  ·  11Comments  ·  Source: vuejs/vue

consider this as the opposite of v-on:

# v-emit
components:
  comp:
    template: "something"
    events:
       toggle: -> @toggle()
    methods:
       toggle: -> #doTheToggleing
template: "<comp v-emit:toggle='toggleComp'></comp>
           <button @click='toggleComp'>Toggle</button>"
methods:
  doSomething: ->
    @toggleComp(someArgs) # in code
emitters:
  toggleComp: null # I'm still unsure if or how to specify default arguments
# alternative
emitters: ["toggleComp"]


# v-call
components:
  comp:
    template: "something"
    methods:
       toggle: -> #doTheToggleing
template: "<comp v-call:toggle='toggleComp'></comp>
           <button @click='toggleComp'>Toggle</button>"
methods:
  doSomething: ->
    @toggleComp(someArgs) # in code
callers:
  toggleComp: null # I'm still unsure if or how to specify default arguments
# alternative
callers: ["toggleComp"]

This would make state management way easier...
of course a shorthand like @ for v-on would be great.

what do you think?

discussion

Most helpful comment

Say you have a very common signal like open or close and you use multiple components from the user space side-by-side - this will be a mess :smile:

Why use the same signal then? I'd never use open twice if I knew I had a modal, a dropdown and a side-nav. I'd rather specify nav:open, modal:open to minimize ambiguity.

For me, $emit, $broadcast and $dispatch have been powerful and simple enough for all use cases. I'm not missing something. Apart from that I see that this could be useful in more complicated situations and could already be built as a custom directive, right?

All 11 comments

I'm not sure I see the benefit. Does not the following achieve the same?

<comp v-ref:comp></comp>
<button @click="$refs.comp.$emit('toggle')">Toggle</button>
<comp v-ref:comp></comp>
<button @click="$refs.comp.toggle()">Toggle</button>

I think $refs don't work in expressions, but I'm unsure.

One clear benefit would be 1:n handling:

I can see it working with a slightly different syntax:

<!-- proxies 'toggle-comp' event to the child as 'toggle' -->
<comp v-emit="{ 'toggle-comp': 'toggle' }"></comp>
<button @click="$emit('toggle-comp')">Toggle</button>
<!-- calls 'toggle' method on the child when parent receives 'toggle-comp' -->
<comp v-call="{ 'toggle-comp': 'toggle' }"></comp>
<button @click="$emit('toggle-comp')">Toggle</button>

More exploration needed.

I think this would solve #2044
and would minimize the need for v-ref (which is good)

currently I think this would be great: (I don't see the benefit of the object syntax?)

<comp v-emit:toggle="toggle-comp"></comp>
<button @click="$emit('toggle-comp')">Toggle</button>

maybe with a shorthand for emit:

<comp ~toggle="toggle-comp"></comp>
<button @click="~toggle-comp">Toggle</button>

@paulpflug the problem is that directives take expression. And v-emit:toggle.literal="toggle-comp" doesn't look much better then v-emit="{ 'toggle-comp': 'toggle' }" to me.

I think with v-for it's better to use dispatch broadcast.

with broadcast you can't control which comp will receive the signal..
Say you have a very common signal like open or close and you use multiple components from the user space side-by-side - this will be a mess :smile:

My actual current intent is to make opening and closing of a component as easy as possible.
Example is you have a side-nav, a modal and a dropdown on one page and each is controlled by one or more buttons. But aside from that you have some logic controlling the actual content. This can be very much for a single page.

I think it would be best to get the trivial - open/closing of things - done with as little effort as possible.

I have worked out 3 ways:

  • to work with toggle signals and v-ref - to verbose
  • to let the component hook up the click event to an element - limited and hidden from the user
  • to work with a two-way bind opened prop - to verbose

I don't like any of them..
So I think we need the opposite of v-on and I'm sure this will solve many unknown problems as well ^^

Say you have a very common signal like open or close and you use multiple components from the user space side-by-side - this will be a mess :smile:

Why use the same signal then? I'd never use open twice if I knew I had a modal, a dropdown and a side-nav. I'd rather specify nav:open, modal:open to minimize ambiguity.

For me, $emit, $broadcast and $dispatch have been powerful and simple enough for all use cases. I'm not missing something. Apart from that I see that this could be useful in more complicated situations and could already be built as a custom directive, right?

could already be built as a custom directive, right?

Only with trade-offs.

<comp ~toggle="toggle-comp"></comp>
<button @click="~toggle-comp">Toggle</button>

is not possible with a custom directive.

@paulpflug the problem is that directives take expression. And v-emit:toggle.literal="toggle-comp" doesn't look much better then v-emit="{ 'toggle-comp': 'toggle' }" to me.

It could simply made a valid expression..

For me, $emit, $broadcast and $dispatch have been powerful and simple enough for all use cases

Sure, it does the work, but so does jquery, I think that is no good argument.
The question is, would it be better than status quo or not?

I want the most simple, clear syntax possible and personally I avoid $refs, $emit, $broadcast, $dispatch and even $els wherever I can - in rare edge cases they are fine, but for my liking to verbose and error prone.

Components and props one the other hand are great and do a great job :smile:

@paulpflug I don't think that such shortcuts will be happening, at least at 1.x. One of the goals is to keep the surface API simple and cohesive.

I've read through the discussion, and I'd say this definitely doesn't belong in core. When your app gets complex, the recommended approach is centralized state management (e.g. Vuex) rather than overloading the custom event system.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

6pm picture 6pm  ·  3Comments

franciscolourenco picture franciscolourenco  ·  3Comments

guan6 picture guan6  ·  3Comments

lmnsg picture lmnsg  ·  3Comments

wufeng87 picture wufeng87  ·  3Comments