Skip to content

为 JSX 设计的一系列宏。需要通过将 macros 设置为 true 来手动启用。

VueVolar
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 到 defineComponentprops 选项中。
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" />
Type 'number' is not assignable to type 'string'.
编译后代码
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 预处理器:cssscsssasslessstyluspostcss
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 < ={.} />
}