You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
4.5 KiB

1 month ago
  1. ## @vue/babel-plugin-transform-vue-jsx
  2. > Babel plugin for Vue 2.0 JSX
  3. ### Babel Compatibility Notes
  4. - 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)
  5. ### Requirements
  6. - 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.
  7. - This is mutually exclusive with `babel-plugin-transform-react-jsx`.
  8. ### Usage
  9. ```bash
  10. npm install @vue/babel-plugin-transform-vue-jsx --save-dev
  11. npm install @vue/babel-helper-vue-jsx-merge-props --save
  12. ```
  13. In your `.babelrc`:
  14. ```json
  15. {
  16. "plugins": ["transform-vue-jsx"]
  17. }
  18. ```
  19. However it is recommended to use the [configurable preset](../babel-preset-jsx/README.md) instead.
  20. ### Details
  21. The plugin transpiles the following JSX:
  22. ```jsx
  23. <div id="foo">{this.text}</div>
  24. ```
  25. To the following JavaScript:
  26. ```js
  27. h(
  28. 'div',
  29. {
  30. attrs: {
  31. id: 'foo',
  32. },
  33. },
  34. [this.text],
  35. )
  36. ```
  37. 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:
  38. ```js
  39. Vue.component('jsx-example', {
  40. render(h) {
  41. // <-- h must be in scope
  42. return <div id="foo">bar</div>
  43. },
  44. })
  45. ```
  46. ### Difference from React JSX
  47. 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:
  48. ```js
  49. render (h) {
  50. return h('div', {
  51. // Component props
  52. props: {
  53. msg: 'hi'
  54. },
  55. // Normal HTML attributes
  56. attrs: {
  57. id: 'foo'
  58. },
  59. // DOM props
  60. domProps: {
  61. innerHTML: 'bar'
  62. },
  63. // Event handlers are nested under "on", though
  64. // modifiers such as in v-on:keyup.enter are not
  65. // supported. You'll have to manually check the
  66. // keyCode in the handler instead.
  67. on: {
  68. click: this.clickHandler
  69. },
  70. // For components only. Allows you to listen to
  71. // native events, rather than events emitted from
  72. // the component using vm.$emit.
  73. nativeOn: {
  74. click: this.nativeClickHandler
  75. },
  76. // Class is a special module, same API as `v-bind:class`
  77. class: {
  78. foo: true,
  79. bar: false
  80. },
  81. // Style is also same as `v-bind:style`
  82. style: {
  83. color: 'red',
  84. fontSize: '14px'
  85. },
  86. // Other special top-level properties
  87. key: 'key',
  88. ref: 'ref',
  89. // Assign the `ref` is used on elements/components with v-for
  90. refInFor: true,
  91. slot: 'slot'
  92. })
  93. }
  94. ```
  95. The equivalent of the above in Vue 2.0 JSX is:
  96. ```jsx
  97. render (h) {
  98. return (
  99. <div
  100. // Component props
  101. propsMsg="hi"
  102. // Normal attributes or component props.
  103. id="foo"
  104. // DOM properties are prefixed with `domProps`
  105. domPropsInnerHTML="bar"
  106. // event listeners are prefixed with `on` or `nativeOn`
  107. onClick={this.clickHandler}
  108. nativeOnClick={this.nativeClickHandler}
  109. // other special top-level properties
  110. class={{ foo: true, bar: false }}
  111. style={{ color: 'red', fontSize: '14px' }}
  112. key="key"
  113. ref="ref"
  114. // assign the `ref` is used on elements/components with v-for
  115. refInFor
  116. slot="slot">
  117. </div>
  118. )
  119. }
  120. ```
  121. ### Component Tip
  122. 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:
  123. ```js
  124. import Todo from './Todo.js'
  125. export default {
  126. render(h) {
  127. return <Todo /> // no need to register Todo via components option
  128. },
  129. }
  130. ```
  131. ### JSX Spread
  132. JSX spread is supported, and this plugin will intelligently merge nested data properties. For example:
  133. ```jsx
  134. const data = {
  135. class: ['b', 'c'],
  136. }
  137. const vnode = <div class="a" {...data} />
  138. ```
  139. The merged data will be:
  140. ```js
  141. { class: ['a', 'b', 'c'] }
  142. ```
  143. ### Vue directives
  144. Vue directives are usable the same way as in template with a few key differences:
  145. 1. You can use directives camelCased instead of kebab-cased (vMyDirective is treated as `v-my-directive`)
  146. 2. You have to use underscore sign instead of dots for modifiers because of JSXIdentifier limitation.
  147. 3. Only runtime directives work (only v-show and custom directives), compile-time directives are out of this project's scope.
  148. A full example would be: `<MyComponent vMyDirective:argument_modifier1_modifier2={someExpression} />`