A babel plugin that provides jsx syntax for vue3
- Supports both
jsx
andtsx
- Same behavior as
Vue3 Compiler
- Fully supports
v-on
/v-model
- Support optimizate mode: analyze
PatchFlags
- Write in Typescript
- Other directives:
v-html
/v-text
- Try to minimize the volume of generated code
npm install @hcysunyang/babel-plugin-vue-next-jsx -D
# or
yarn add @hcysunyang/babel-plugin-vue-next-jsx -D
{
"presets": [
"@babel/env"
],
"plugins": [
"@hcysunyang/vue-next-jsx"
]
}
Please read this thread: vuejs/jsx-vue2#141
For the sake of type hinting and type safety, we recommend using the following syntax:
<!-- value -->
<input vModel={ [refVal.value] } />
<!-- value + array modifiers -->
<input vModel={ [refVal.value, ['number', 'trim']] } />
<!-- value + object modifiers -->
<input vModel={ [refVal.value, { number: true }] } />
<!-- modifiers as a variable -->
<input vModel={ [refVal.value, modifiers] } />
<!-- value -->
<Comp vModel={ [refVal.value] } />
<!-- value + array modifiers -->
<Comp vModel={ [refVal.value, 'modelValue', ['a', 'b']] } />
<!-- value + object modifiers -->
<Comp vModel={ [refVal.value, 'modelValue', { a: true, b: true }] } />
<!-- value + propName -->
<Comp vModel={ [refVal.value, 'foo'] } />
<!-- value + dynamic propName -->
<Comp vModel={ [refVal.value, refName.value] } />
<!-- value + dynamic propName + modifiers -->
<Comp vModel={ [refVal.value, refName.value, ['a', 'b']] } />
<!-- modifiers as a variable -->
<Comp vModel={ [refVal.value, refName.value, modifiers] } />
<div onClick={ handler }></div>
<div onClick={ withModifiers(handler, ['self']) }></div>
For type hints, you can check our dts test:
{
// ...
"compilerOptions": {
"types": ["@hcysunyang/babel-plugin-vue-next-jsx"],
}
// ...
}
We often do this in template:
<p v-on:click.stop="handler"></p>
In (j|t)sx
:
<p v-on-click_stop="handler"></p>
tsx
does not allow to use :
and .
as attribute name
If it is available in the template, it is available in j/tsx
too, here are some examples:
<div v-on-click_middle={ handler }></div>
<div v-on-click_stop={ handler }></div>
<div v-on-click_right={ handler }></div>
<div v-on-keyup_esc={ handler }></div>
<div v-on={ obj }></div>
<input v-model={ refVal.value }/>
<input v-model={ refVal.value } :type={ refType.value }/>
<select v-model={ refVal.value }/>
<textarea v-model={ refVal.value }/>
v-model
in the component:
<Comp v-model-foo_a={ refVal.value }/>
The generated code is:
createVNode(Comp, {
"foo": ref.val,
"onUpdate:foo": $event => ref.val = $event,
"fooModifiers": {
"a": true,
"b": true
}
})
This is consistent with Vue3 Compiler behavior.
In fact, we don't need v-bind
in (j|t)sx
, we can use jsxExpressionContainer
and jsxSpreadAttribute
directly:
<Comp foo={ refVal.value } { ...props } bar="bar" />
The generated code is:
const el = createVNode(Comp,
mergeProps(
{ foo: refVal.value },
{ ...props },
{ bar: "bar" }
)
)
I don’t want to support v-slot
. One of the most important reasons is that in tsx
: the type of scopedSlot is lost. It is recommended to do this(and this is the only way):
const App = {
setup() {
return () => {
const slots = {
default: () => [ <p>default</p> ],
foo: ({ val }) => [ <p>{ val }</p> ]
}
return <Comp>{ slots }</Comp>
}
}
}
In Vue3, the children of KeepAlive and Teleport components will not be built as slots
, so you can use them as in the template:
Since Vue3 supports multiple root elements, so we need to support Fragment
:
<>
<p>foo</p>
<div>bar</div>
</>
Vue3
makes full use of compile-time information to generate PatchFlags
for runtime update performance improvement, vue-next-jsx
behaves as Vue3 Compiler
after enabling optimization mode.
In the babel.config.json
file:
{
"presets": [
"@babel/env"
],
"plugins": [
["@hcysunyang/vue-next-jsx", {
// Enabling optimization mode
"optimizate": true
}]
]
}
If you install vue
instead of @vue/runtime-dom
then you don’t need to do anything, but if you install @vue/runtime-dom
, then you need to specify source
:
{
"presets": [
"@babel/env"
],
"plugins": [
["@hcysunyang/vue-next-jsx", {
// Specify source
"source": "@vue/runtime-dom"
}]
]
}
Just like using them in template:
<p v-html={ refHtml.value }></p>
<p v-text={ refText.value }></p>
Supported:
v-show
<p v-show={ refVal.value }></p>