vuejs / babel-plugin-transform-vue-jsx

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

Object spread operator isn't applied correctly #143

Closed petervmeijgaard closed 6 years ago

petervmeijgaard commented 6 years ago

Goodday!

I ran into an issue when I was applying the spread operator on a custom component with JSX syntax. The properties that I want to apply, aren't applied correctly.

Example:

// UIButton.js

/* @vue/component */
export default {
  name: 'UIButton',

  props: {
    isExternal: {
      type: Boolean,
      required: false,
      default: () => false,
    },
  },

  computed: {
    classes() {
      return [ 'computed', 'classes' ];
    },

    children() {
      return this.hasSlot() ? [...this.$slots.default] : [this.content];
    },
  },

  methods: {
    hasSlot(slotName = 'default') {
      return !!this.$slots[slotName];
    },
  },

  /* eslint-disable-next-line no-unused-vars */
  render(h) {
    let props = {
      class: this.classes,
    };

    if (this.isExternal) {
      props.target = '_blank';
      props.rel = 'noopener noreferrer';
    }

    /*
     * Will return in this:
     * {
     *    class: ['computed', 'classes'],
     *    rel: 'noopener noreferrer',
     *    target: '_blank'
     * }
     */
    console.log(props);

    return (
      <a {...props}>
        {this.children}
      </a>
    );
  },
};

When using this example, you'll see that the classes are applied correctly, but the rel and target are not.


As you can see, the console.log is showing the object with all the properties. screenshot_20180713_215547

But the rel and target aren't rendered. screenshot_20180713_215958

nickmessing commented 6 years ago

That's expcted, you need to pass them as attrs:

  render(h) {
    let props = {
      class: this.classes,
    };

    if (this.isExternal) {
      props.attrs = { target: '_blank', rel: 'noopener noreferrer' }
    }
    console.log(props);

    return (
      <a {...props}>
        {this.children}
      </a>
    );

I think this one is correct, Vue JSX is slightly different from react, you can find out more in createElement Arguments

petervmeijgaard commented 6 years ago

Ah yes! That did the trick! I'm working with both Vue and React, so I was confused why it didn't work.