Skip to content

Instantly share code, notes, and snippets.

@KagamiChan
Last active March 4, 2018 17:47
Show Gist options
  • Save KagamiChan/0a8d005db522be9d3a081b79b1f9c3dc to your computer and use it in GitHub Desktop.
Save KagamiChan/0a8d005db522be9d3a081b79b1f9c3dc to your computer and use it in GitHub Desktop.
How to turn vue template into JSX, a.k.a using JSX in Vue

How to turn vue template into JSX a.k.a using JSX in Vue

v-bind & v-on

<vue-component :value="value" @click="handleClick" />
<input :value="value" @click="handleClick" />
<vue-component value={this.value} onClick={this.handleClick }/>
<input domPropsValue={this.value} onClick={this.handleClick} />

Notes:

  1. if the event's name is kebab-case, say, foo-bar, use onFoo-bar
  2. some vue 1.0 compatible/legacy components take also on-foo-bar as prop besides @foo-bar
  3. for native controls, use domPropsValue instead of value (see here)
  4. for modifers, say, @submit.native, use navtiveOnSubmit, for other possibilities, see here

v-model

Might be supported with babel plugin (see here), but you could write in a reactive way:

<vue-component v-model="value" />
<input v-model="value" />
<vue-component value={this.value} onInput={(value) => { this.value = value }}/>
<input domPropsValue={this.value} onInput={(value) => { this.value = value }} />

Attention: the arrow function in onInput is renewed after each update, it might cause performance issues

v-for

<span v-for="foo in bar" :key="foo.label" >
  {{ foo.value }}
</span>
{
  bar.map(foo => (
    <span key={foo.label}>
      { foo.value }
    </span>
  ))
}

Notes:

  1. if bar is an object, use Object.keys(bar) to get bar's enumerable keys and then you can iterate over keys. Other possibilities are Object.prototype.values, Object.prototype.entries and lodash's map method
  2. in JSX mode, there's no key warning, But using key is highly recommended because of Vue's DOM update strategy (Vue tries to reuse DOM nodes, and different keys prevent the reusage).

v-if, v-else

<span v-if="show">foo</span>
<span v-else>bar</span>
{
  this.show
    ? <span>foo</span>
    : <span>bar</span>
}
{
  this.show &&
    <span>foobar</span>
}

Notes:

  1. if show is a Number, show && ... will result in displaying a number 0 if it is 0. Use !!show or Boolean(show) to turn it into Boolean
  2. you don't have to change v-show because it is transformed differently, in some cases transforming v-show might result in unexpected behaviours

Slot & scoped slot

The syntax will be the same if you're passing scopes to a component.

<vue-component>
  <div>foobar</div>
  <div slot="foo">bar</div>
</vue-component>
<vue-component>
  <div>foobar</div>
  <div slot="foo">bar</div>
</vue-component>

You may also use slots prop:

<vue-component
  slots={{
    default: () => (<div>foobar</div>),
    foo: () => (<div>bar</div>),
  }}
/>

For scoped slots, write like this:

<vue-component>
  <div slot="foo" scope="props">{{ props.bar }}</div>
</vue-component>
<vue-component
  scopedSlots={{
    foo: (props) => (<div>{props.bar}</div>),
  }}
/>

If you are designing a component that accepts scopes

<div>
  <slot name="foo">
  </slot>
</div>
<div>
  {
    this.$slots.foo
  }
</div>

Using vue components

You don't have to register a component in components field, simply use it in a React way.

import FooBar from './foor-bar'

export default {
  render() {
    return <FooBar />
  }
}

Using class syntax

You could use class syntax similar to React's thanks to vue-class-component.

import Vue from 'vue'
import Component from 'vue-class-component'

@Component()
export default class FooBar {
  render() {
    return <span>foobar</span>
  }
}

You may find more detail on vue-class-component's readme.

To note: the ES decorator spec (@) is not stable now (as of Aug. 2017) and is likely to change in the future.

Passing unregistered props and listeners to child components as {...props} in React

<vue-component
  {...{
    attrs: this.$attrs,
    listeners: this.$listeners,
  }}
/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment