vuejs / babel-plugin-transform-vue-jsx

babel plugin for vue 2.0 jsx
1.85k stars 132 forks source link

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

Open koresar opened 6 years ago

koresar commented 6 years ago

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.

Akryum commented 6 years ago

You can use JSX spread:

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

return <MyComponent {...data} />
koresar commented 6 years ago

Thanks. Trying it now.

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

koresar commented 6 years ago

Does your reply mean that these:

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

will also work?

LinusBorg commented 6 years ago

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" />
koresar commented 6 years ago

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
LinusBorg commented 6 years ago

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}
koresar commented 6 years ago

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'}} />
LinusBorg commented 6 years ago

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.

koresar commented 6 years ago

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:

Cons:

nickmessing commented 6 years ago

@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.

koresar commented 6 years ago

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"?

nickmessing commented 6 years ago

@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.

wegorich commented 6 years ago

@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

HerbLuo commented 6 years ago

also iview Scroll