Spaces:
Sleeping
Sleeping
## @vue/babel-plugin-transform-vue-jsx | |
> Babel plugin for Vue 2.0 JSX | |
### Babel Compatibility Notes | |
- This repo is only compatible with Babel 7.x, for 6.x please use [vuejs/babel-plugin-transform-vue-jsx](https://github.com/vuejs/babel-plugin-transform-vue-jsx) | |
### Requirements | |
- Assumes you are using Babel with a module bundler e.g. Webpack, because the spread merge helper is imported as a module to avoid duplication. | |
- This is mutually exclusive with `babel-plugin-transform-react-jsx`. | |
### Usage | |
```bash | |
npm install @vue/babel-plugin-transform-vue-jsx --save-dev | |
npm install @vue/babel-helper-vue-jsx-merge-props --save | |
``` | |
In your `.babelrc`: | |
```json | |
{ | |
"plugins": ["transform-vue-jsx"] | |
} | |
``` | |
However it is recommended to use the [configurable preset](../babel-preset-jsx/README.md) instead. | |
### Details | |
The plugin transpiles the following JSX: | |
```jsx | |
<div id="foo">{this.text}</div> | |
``` | |
To the following JavaScript: | |
```js | |
h( | |
'div', | |
{ | |
attrs: { | |
id: 'foo', | |
}, | |
}, | |
[this.text], | |
) | |
``` | |
Note the `h` function, which is a shorthand for a Vue instance's `$createElement` method, must be in the scope where the JSX is. Since this method is passed to component render functions as the first argument, in most cases you'd do this: | |
```js | |
Vue.component('jsx-example', { | |
render(h) { | |
// <-- h must be in scope | |
return <div id="foo">bar</div> | |
}, | |
}) | |
``` | |
### Difference from React JSX | |
First, Vue 2.0's vnode format is different from React's. The second argument to the `createElement` call is a "data object" that accepts nested objects. Each nested object will be then processed by corresponding modules: | |
```js | |
render (h) { | |
return h('div', { | |
// Component props | |
props: { | |
msg: 'hi' | |
}, | |
// Normal HTML attributes | |
attrs: { | |
id: 'foo' | |
}, | |
// DOM props | |
domProps: { | |
innerHTML: 'bar' | |
}, | |
// Event handlers are nested under "on", though | |
// modifiers such as in v-on:keyup.enter are not | |
// supported. You'll have to manually check the | |
// keyCode in the handler instead. | |
on: { | |
click: this.clickHandler | |
}, | |
// For components only. Allows you to listen to | |
// native events, rather than events emitted from | |
// the component using vm.$emit. | |
nativeOn: { | |
click: this.nativeClickHandler | |
}, | |
// Class is a special module, same API as `v-bind:class` | |
class: { | |
foo: true, | |
bar: false | |
}, | |
// Style is also same as `v-bind:style` | |
style: { | |
color: 'red', | |
fontSize: '14px' | |
}, | |
// Other special top-level properties | |
key: 'key', | |
ref: 'ref', | |
// Assign the `ref` is used on elements/components with v-for | |
refInFor: true, | |
slot: 'slot' | |
}) | |
} | |
``` | |
The equivalent of the above in Vue 2.0 JSX is: | |
```jsx | |
render (h) { | |
return ( | |
<div | |
// Component props | |
propsMsg="hi" | |
// Normal attributes or component props. | |
id="foo" | |
// DOM properties are prefixed with `domProps` | |
domPropsInnerHTML="bar" | |
// event listeners are prefixed with `on` or `nativeOn` | |
onClick={this.clickHandler} | |
nativeOnClick={this.nativeClickHandler} | |
// other special top-level properties | |
class={{ foo: true, bar: false }} | |
style={{ color: 'red', fontSize: '14px' }} | |
key="key" | |
ref="ref" | |
// assign the `ref` is used on elements/components with v-for | |
refInFor | |
slot="slot"> | |
</div> | |
) | |
} | |
``` | |
### Component Tip | |
If a custom element starts with lowercase, it will be treated as a string id and used to lookup a registered component. If it starts with uppercase, it will be treated as an identifier, which allows you to do: | |
```js | |
import Todo from './Todo.js' | |
export default { | |
render(h) { | |
return <Todo /> // no need to register Todo via components option | |
}, | |
} | |
``` | |
### JSX Spread | |
JSX spread is supported, and this plugin will intelligently merge nested data properties. For example: | |
```jsx | |
const data = { | |
class: ['b', 'c'], | |
} | |
const vnode = <div class="a" {...data} /> | |
``` | |
The merged data will be: | |
```js | |
{ class: ['a', 'b', 'c'] } | |
``` | |
### Vue directives | |
Vue directives are usable the same way as in template with a few key differences: | |
1. You can use directives camelCased instead of kebab-cased (vMyDirective is treated as `v-my-directive`) | |
2. You have to use underscore sign instead of dots for modifiers because of JSXIdentifier limitation. | |
3. Only runtime directives work (only v-show and custom directives), compile-time directives are out of this project's scope. | |
A full example would be: `<MyComponent vMyDirective:argument_modifier1_modifier2={someExpression} />` | |