Macros
A collection of macros for JSX. They are need to manually enabled by set macros
to true
.
Directive | Vue | Volar |
---|---|---|
defineComponent | ✅ | ✅ |
defineModel | ✅ | ✅ |
defineSlots | ✅ | ✅ |
defineExpose | ✅ | ✅ |
defineStyle | ✅ | ✅ |
Setup
ts
import { defineConfig } from 'vite'
import vueJsxVapor from 'vue-jsx-vapor/vite'
export default defineConfig({
plugins: [
vueJsxVapor({
macros: true,
}),
],
})
ts
import vueJsxVapor from 'vue-jsx-vapor/volar'
export default {
plugins: [
vueJsxVapor({
macros: true,
}),
],
}
defineComponent
- Support
await
keyword. - Automatically collects used props to the defineComponent's props option.
tsx
import { , , , } from 'vue'
const = (
async (: {
?: string
?: string
// ^ unused prop will be as a fallthrough attribute.
}) => {
await ()
const = ()
return (
<>
< {...}>{.}</>
</>
)
},
)
export default () => (
<>
< ="foo" ="bar" />
</>
)
Compiled Code
tsx
import { defineComponent, useAttrs, withAsyncContext } from 'vue'
defineComponent(
async (props) => {
let __temp, __restore
;([__temp, __restore] = withAsyncContext(() => nextTick())),
await __temp,
__restore()
const attrs = useAttrs()
return () => (
<div>
<span {...attrs}>{props.foo}</span>
</div>
)
},
{ props: { foo: null } },
)
- The destructured props will be automatically restructured.
- If the prop's default value ends with
!
, the prop will be inferred as required. - If a rest prop is defined, it will be converted to
useAttrs()
, and theinheritAttrs
option will default tofalse
.
tsx
import { } from 'vue'
const = (
<,>({ = as , = ''!, ... }) => {
return (
<>
< {...}>{}</>
</>
)
},
)
export default () => <<string> foo={1} ="bar" />
Compiled Code
tsx
import { defineComponent } from 'vue'
import { createPropsDefaultProxy } from '/vue-macros/jsx-macros/with-defaults'
defineComponent(
(_props) => {
const props = createPropsDefaultProxy(_props, { bar: '' })
const attrs = useAttrs()
return () => (
<div>
<span {...attrs}>{props.foo}</span>
</div>
)
},
{ props: { foo: null, bar: { required: true } }, inheritAttrs: false },
)
defineModel
- Doesn't support hyphenated model names.
- Will be inferred as a required prop when the expression ends with
!
. - The modified model's value can be read synchronously, without needing to
await nextTick()
. Related issue
tsx
import { } from 'vue'
function () {
const = <string>()!
. = 'foo'
return <>{.}</>
}
export default () => {
const = ('')
return < ={.} />
}
Compiled Code
tsx
import { ref } from 'vue'
import { useModel } from '/vue-macros/jsx-macros/use-model'
function Comp(_props: {
modelValue: string
'onUpdate:modelValue': (value: string) => any
}) {
const modelValue = useModel<string>(_props, 'modelValue', { required: true })
modelValue.value = 'foo'
return <div>{modelValue.value}</div>
}
defineSlots
- If using generics to define slots, all slots will be optional.
tsx
const = <{
: () => any
}>()
.?.()
// ^ optional
- Support default slots (Recommended).
tsx
function <const >() {
const = ({
: (: { ?: }) => <>title slot: {.}</>,
: (: { : number }) => <>default slot: {.}</>,
})
return (
<>
<. />
<. ={1} />
</>
)
}
export default () => (
<<1>>
<template v-slot={{ }}>{}</template>
<template v-slot:={{ }}>{}</template>
</>
)
defineExpose
Just like in Vue SFC.
tsx
import { } from 'vue-jsx-vapor'
const = <,>({ = as }) => {
({
,
})
return < />
}
export default () => {
const = ()
.?.
return < ={} ={1 as } />
}
Compiled Code
tsx
import { currentInstance } from 'vue'
import { useRef } from 'vue-jsx-vapor'
import { useExpose } from '/vue-macros/jsx-macros/use-expose'
const Comp = ({ foo }) => {
currentInstance.exposed = {
foo,
}
return <div />
}
defineStyle
ts
declare function defineStyle(
style: string,
options?: { scoped?: boolean },
): void
- Support CSS-variable and JS-variable binding.
- Support defining multiple style macros in a file.
- Support CSS pre-processors:
css
,scss
,sass
,less
,stylus
,postcss
.
ts
defineStyle.scss(`...`)
defineStyle.stylus(`...`)
// ...
- Support scoped mode.
- If defined at the top level of the file, the scoped option defaults to
false
. - If defined within a function, the scoped option defaults to
true
.
- If defined at the top level of the file, the scoped option defaults to
tsx
function ({ = 'red' }) {
.(`
.foo {
color: ${};
:deep(.bar) {
color: blue;
}
}
`)
return < ="red" ="foo bar">foo</>
}
(`
.bar {
background: black;
}
`)
- Support
css modules
, if the macro is an assignment expression.
tsx
export default () => {
const = .(`
.foo {
color: blue;
.bar {
background: red;
}
}
`)
return < ={.} />
}