babel-plugin-transform-vue-jsx icon indicating copy to clipboard operation
babel-plugin-transform-vue-jsx copied to clipboard

How to pass props that collid with the event naming scheme (`onEventName`)?

Open koresar opened this issue 6 years ago • 14 comments

In the README Difference from React JSX section it says:

render (h) {
  return h('div', {
    // Component props
    props: {
      msg: 'hi'
    },

I'm looking for that msg: 'hi' in the The equivalent of the above in Vue 2.0 JSX and cannot find it. So how would I pass props?

Namely, I want to pass a props named "onUpload", but unfortunately this plugin automagically subscribes to the "upload" event instead.

Please help.

koresar avatar Dec 01 '17 09:12 koresar

You can use JSX spread:

const data = {
  props: {
    onUpload: 'foo',
  },
}

return <MyComponent {...data} />

Akryum avatar Dec 01 '17 09:12 Akryum

Thanks. Trying it now.

Still, that msg: 'hi' is confusing in the README.

koresar avatar Dec 01 '17 12:12 koresar

Does your reply mean that these:

return <MyComponent {...{props:{onUpload: 'foo'}}} />
return <MyComponent props={{onUpload: 'foo'}} />

will also work?

koresar avatar Dec 01 '17 12:12 koresar

I think your confusion has to do with the fact that the examle renders a div element with props, which simply doesn't make sense in "real life".

render (h) {
  return h('my-component', {
    // Component props
    props: {
      msg: 'hi'
    },

is the same as:

<my-component msg="hi" />

LinusBorg avatar Dec 01 '17 12:12 LinusBorg

Then the README is missing this msg="hi" you have just mentioned @LinusBorg

However, my problem is that code

render (h) {
  return h('my-component', {
    // Component props
    props: {
      onUpload: 'foo'
    },

does not pass onUpload as a prop

<MyComponent onUpload="foo"> // DOES NOT HAPPEN

koresar avatar Dec 01 '17 12:12 koresar

That's because everything with on* is turned into an event listener:

onUpload={this.foo} => v-on:upload="foo"

Look at the example again:

// event listeners are prefixed with `on` or `nativeOn`
onClick={this.clickHandler}

LinusBorg avatar Dec 01 '17 12:12 LinusBorg

Thank you, I saw that.

Probably, I need to clarify why I really need to pass a prop which name starts with on. http://element.eleme.io/#/en-US/component/upload#attributes As you can see a bunch of attributes in this third party component starts with on-. I cannot change the prop names.

As the result JSX is impossible to use with the component.

That's why I asked:

Will that work?

return <MyComponent {...{props:{onUpload: 'foo'}}} />
return <MyComponent props={{onUpload: 'foo'}} />

koresar avatar Dec 01 '17 12:12 koresar

Thank you, now I get it finally :D

I took the part you wrote in bold letters to be the core of your problem, but it wasn't.

The simple, yet probably unsatisfying answer: You can't use JSX in that case. every JSX Attribute starting with on and followed by an upper case character will be turned into an event instead of a prop. We needed a way to make event listeners possible, and since JSX doesn't like colons in its attribute names, we chose this pattern.

You will have to write a plain call to h() for that.

return h('my-component',  {
  props: {
    onUpload: this.foo,
  }
})

(That being said, I have no idea why the authors of that third-party component don't use events for callbacks, as you usually do in Vue. Probably because they wanted an easy way to pass them on to child components, and that wasn't possible as easily before we introduced $listeners in 2.3 or 2.4)

So: Not a bug in the README - expected behaviour that you have to work around due to technical limitations we have when translating JSX to Vue.

LinusBorg avatar Dec 01 '17 12:12 LinusBorg

Thanks Linus!

Since original Vue syntax is v-on:upload should we just follow the same pattern and minimise the unfortunate collisions even further and allow only this syntax: v-on-upload.

I mean do not treat onUpload or on-upload as event subscription. Only treat v-on-upload.

Pros:

  • Less collisions (like my above)
  • Quite similar to original Vue syntax
  • Opens the road for v-bind:foo -> v-bind-foo, and others like v-model, v-pre, v-cloak, v-show, v-html, v-text, etc.

Cons:

  • breaking change

koresar avatar Dec 01 '17 13:12 koresar

@koresar, I would vote against that because in vue we have events that are completely replace the need for "onSomeEvent" props. If there are components that use that kind of API that is a poor design decision in Vue world IMO.

nickmessing avatar Jan 14 '18 15:01 nickmessing

Thanks @nickmessing I'm not quite sure which events you are talking about. Could you please list one or two "events that are completely replace the need"?

koresar avatar Jan 14 '18 22:01 koresar

@koresar, so, instead of having a prop named "onSubmit" for a component, you declare an event named "submit" in the component and use that instead.

nickmessing avatar Jan 14 '18 23:01 nickmessing

@nickmessing it's ok when you doing it in your code. But when you start using external components you are in trouble.

for example http://doc.huangsw.com/vue-easytable/app.html#/table they have on-custom-comp event. I have no idea how to subscribe to it

wegorich avatar Jan 31 '18 09:01 wegorich

also iview Scroll

HerbLuo avatar Feb 18 '18 11:02 HerbLuo