123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- ## @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} />`
|