宏
为 JSX 设计的一系列宏。需要通过将 macros
设置为 true
来手动启用。
宏 | Vue | Volar |
---|---|---|
defineComponent | ✅ | ✅ |
defineModel | ✅ | ✅ |
defineSlots | ✅ | ✅ |
defineExpose | ✅ | ✅ |
defineStyle | ✅ | ✅ |
配置
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
- 支持
await
关键字。 - 自动收集使用到的 props 到
defineComponent
的props
选项中。
tsx
import { , , , } from 'vue'
const = (
async (: {
?: string
?: string
// ^ 未使用的 prop 将作为 fallthrough attribute。
}) => {
await ()
const = ()
return (
<>
< {...}>{.}</>
</>
)
},
)
export default () => (
<>
< ="foo" ="bar" />
</>
)
编译后代码
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 } },
)
- 解构的 props 将被自动重构。
- 如果 prop 的默认值以
!
结尾,则该 prop 将被推断为必需的。 - 如果定义了 rest prop,它将被转换为
useAttrs()
,并且inheritAttrs
选项将默认为false
。
tsx
import { } from 'vue'
const = (
<,>({ = as , = ''!, ... }) => {
return (
<>
< {...}>{}</>
</>
)
},
)
export default () => <<string> foo={1} ="bar" />
编译后代码
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
- 不支持带连字符的 model 名称。
- 当表达式以
!
结尾时,将被推断为必需的 prop。 - 修改后的 model 值可以同步读取,无需
await nextTick()
。相关 issue
tsx
import { } from 'vue'
function () {
const = <string>()!
. = 'foo'
return <>{.}</>
}
export default () => {
const = ('')
return < ={.} />
}
编译后代码
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
- 如果使用泛型定义插槽,所有插槽都将是可选的。
tsx
const = <{
: () => any
}>()
.?.()
// ^ optional
- 支持默认插槽(推荐)。
tsx
function <const >() {
const = ({
: (: { ?: }) => <>title slot: {.}</>,
: (: { : number }) => <>default slot: {.}</>,
})
return (
<>
<. />
<. ={1} />
</>
)
}
export default () => (
<<1>>
<template v-slot={{ }}>{}</template>
<template v-slot:={{ }}>{}</template>
</>
)
defineExpose
与在 Vue SFC 中一样。
tsx
import { } from 'vue-jsx-vapor'
const = <,>({ = as }) => {
({
,
})
return < />
}
export default () => {
const = ()
.?.
return < ={} ={1 as } />
}
编译后代码
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
- 支持 CSS 变量和 JS 变量绑定。
- 支持在文件中定义多个样式宏。
- 支持 CSS 预处理器:
css
、scss
、sass
、less
、stylus
、postcss
。
ts
defineStyle.scss(`...`)
defineStyle.stylus(`...`)
// ...
- 支持作用域模式。
- 如果在文件顶层定义,
scoped
选项默认为false
。 - 如果在函数内部定义,
scoped
选项默认为true
。
- 如果在文件顶层定义,
tsx
function ({ = 'red' }) {
.(`
.foo {
color: ${};
:deep(.bar) {
color: blue;
}
}
`)
return < ="red" ="foo bar">foo</>
}
(`
.bar {
background: black;
}
`)
- 支持
css modules
,如果宏是赋值表达式。
tsx
export default () => {
const = .(`
.foo {
color: blue;
.bar {
background: red;
}
}
`)
return < ={.} />
}