Explore more macros and syntax sugar to Vue.
—
Shorthand syntax and convenience features for Vue templates and scripts.
Shorthand syntax for emitting events.
/**
* Short emit function with simplified syntax
* @param name - Event name from defined emits
* @param args - Event arguments
*/
declare function emits<T extends Record<string, any>>(
name: keyof T,
...args: any[]
): void;
// Configuration options
interface OptionsShortEmits extends BaseOptions {
/** Enable short emits syntax */
enabled?: boolean;
}Usage Examples:
<script setup>
// Define emits normally
const emit = defineEmits<{
update: [value: string];
change: [oldValue: string, newValue: string];
delete: [];
select: [item: { id: number; name: string }];
}>();
// Short emit syntax (alternative to emit())
function handleUpdate(value: string) {
emits('update', value); // Same as: emit('update', value)
}
function handleChange(old: string, newVal: string) {
emits('change', old, newVal); // Same as: emit('change', old, newVal)
}
function handleDelete() {
emits('delete'); // Same as: emit('delete')
}
</script>Shorthand syntax for v-model bindings.
/**
* Short v-model syntax using :: prefix
*/
// Template syntax: ::modelValue instead of v-model:modelValue
// Template syntax: ::checked instead of v-model:checked
// Configuration options
interface OptionsShortVmodel extends BaseOptions {
/** Enable short v-model syntax */
enabled?: boolean;
}Usage Examples:
<template>
<!-- Standard v-model -->
<input v-model="message" />
<input v-model:checked="isChecked" />
<!-- Short v-model syntax -->
<input ::message /> <!-- Same as v-model="message" -->
<input ::checked /> <!-- Same as v-model:checked="checked" -->
<!-- Works with components -->
<CustomInput ::value /> <!-- Same as v-model:value="value" -->
<Modal ::visible /> <!-- Same as v-model:visible="visible" -->
</template>
<script setup>
const message = ref('');
const isChecked = ref(false);
const value = ref('');
const visible = ref(false);
</script>Shorthand syntax for prop binding.
/**
* Short bind syntax using : prefix for same-named props
*/
// Template syntax: :propName instead of :prop-name="propName"
// Configuration options
interface OptionsShortBind extends BaseOptions {
/** Enable short bind syntax */
enabled?: boolean;
}Usage Examples:
<template>
<!-- Standard prop binding -->
<MyComponent :title="title" :count="count" :is-active="isActive" />
<!-- Short bind syntax (same variable name as prop) -->
<MyComponent :title :count :is-active />
<!-- Mixed usage -->
<MyComponent
:title <!-- Short: same as :title="title" -->
:count="newCount" <!-- Full: different variable name -->
:is-active <!-- Short: same as :is-active="isActive" -->
/>
<!-- Works with kebab-case to camelCase conversion -->
<MyComponent :user-name /> <!-- Same as :user-name="userName" -->
</template>
<script setup>
const title = ref('My Title');
const count = ref(10);
const newCount = ref(20);
const isActive = ref(true);
const userName = ref('john');
</script>Shorthand syntax for boolean props.
/**
* Boolean prop syntax using + prefix
*/
// Template syntax: +propName instead of :prop-name="true"
// Template syntax: -propName instead of :prop-name="false"
// Configuration options
interface OptionsBooleanProp extends BaseOptions {
/** Enable boolean prop syntax */
enabled?: boolean;
}Usage Examples:
<template>
<!-- Standard boolean props -->
<MyButton :disabled="true" :loading="false" />
<!-- Boolean prop syntax -->
<MyButton +disabled -loading /> <!-- Same as :disabled="true" :loading="false" -->
<!-- Mixed with regular props -->
<MyModal
+visible <!-- Same as :visible="true" -->
-closeable <!-- Same as :closeable="false" -->
title="My Modal" <!-- Regular prop -->
/>
<!-- Conditional boolean props -->
<MyComponent
+active="isActive" <!-- Same as :active="isActive" -->
+large="size === 'large'" <!-- Same as :large="size === 'large'" -->
/>
</template>
<script setup>
const isActive = ref(true);
const size = ref('large');
</script>Enhanced destructuring for props with method chaining.
/**
* Chain call destructuring for props
*/
declare const $defineProps: <T>() => ChainCallDestructure<T>;
interface ChainCallDestructure<T> {
[K in keyof T]: PropChain<T[K]>;
}
interface PropChain<T> {
/** Set default value */
default(value: T | (() => T)): PropChain<T>;
/** Mark as required */
required(): PropChain<T>;
/** Add validator function */
validator(fn: (value: T) => boolean): PropChain<T>;
}Usage Examples:
<script setup>
// Chain call destructuring
const {
title,
count,
user,
options
} = $defineProps<{
title: string;
count: number;
user: { name: string; age: number };
options: string[];
}>()
.title.required()
.count.default(0).validator(n => n >= 0)
.user.default(() => ({ name: '', age: 0 }))
.options.default(() => []);
// Direct usage in template and script
console.log(title); // Type: string (required)
console.log(count); // Type: number (default: 0)
console.log(user.name); // Type: string
console.log(options); // Type: string[] (default: [])
</script>Additional template syntax shortcuts.
/**
* Template syntax shortcuts and abbreviations
*/
// Event listener shortcuts
// @click -> v-on:click
// @input -> v-on:input
// Slot shortcuts
// #default -> v-slot:default
// #header -> v-slot:header
// Directive shortcuts
// v-if -> v-if
// v-show -> v-show
// v-for -> v-forUsage Examples:
<template>
<!-- Event shortcuts (built into Vue) -->
<button @click="handleClick">Click</button>
<input @input="handleInput" @change="handleChange" />
<!-- Slot shortcuts (built into Vue) -->
<MyComponent>
<template #header="{ title }">
<h1>{{ title }}</h1>
</template>
<template #default>
<p>Default content</p>
</template>
<template #footer>
<p>Footer content</p>
</template>
</MyComponent>
<!-- Short syntax combinations -->
<MyCard
+visible <!-- Boolean prop -->
:title <!-- Short bind -->
::selected <!-- Short v-model -->
@close="onClose" <!-- Event -->
/>
</template>
<script setup>
const title = ref('Card Title');
const selected = ref(false);
function handleClick() {
console.log('Clicked');
}
function handleInput(event: Event) {
console.log('Input:', (event.target as HTMLInputElement).value);
}
function handleChange(event: Event) {
console.log('Changed:', (event.target as HTMLInputElement).value);
}
function onClose() {
console.log('Card closed');
}
</script>Combining multiple syntax sugar features.
/**
* Combined syntax sugar usage patterns
*/
// Combining short bind + boolean props + short v-model
// <Component :title +active ::value @event="handler" />
// Combining chain call + short syntax
// const { prop } = $defineProps<T>().prop.default(value);Usage Examples:
<template>
<!-- All syntax sugar combined -->
<AdvancedComponent
:title <!-- Short bind -->
:count="newCount" <!-- Regular bind -->
+visible <!-- Boolean prop (true) -->
-disabled <!-- Boolean prop (false) -->
::modelValue <!-- Short v-model -->
::checked <!-- Short v-model named -->
@update="onUpdate" <!-- Event handler -->
@close="onClose" <!-- Event handler -->
>
<template #header="{ data }">
<h2>{{ data.title }}</h2>
</template>
</AdvancedComponent>
</template>
<script setup>
// Combined prop definition with syntax sugar
const {
title,
description,
count,
isActive
} = $defineProps<{
title: string;
description?: string;
count: number;
isActive: boolean;
}>()
.title.required()
.description.default('No description')
.count.default(0).validator(n => n >= 0)
.isActive.default(true);
// Short emits
const emit = defineEmits<{
update: [value: any];
close: [];
}>();
// Usage
const newCount = ref(42);
const modelValue = ref('');
const checked = ref(false);
function onUpdate(value: any) {
emits('update', value); // Short emit syntax
}
function onClose() {
emits('close'); // Short emit syntax
}
</script>Supporting types for syntax sugar features.
// Configuration base
interface BaseOptions {
version?: string;
isProduction?: boolean;
root?: string;
include?: string | RegExp | (string | RegExp)[];
exclude?: string | RegExp | (string | RegExp)[];
}
// Emit function type
type EmitFunction<T> = T extends Record<string, any>
? <K extends keyof T>(event: K, ...args: T[K] extends (...args: infer P) => any ? P : [T[K]]) => void
: (event: string, ...args: any[]) => void;
// Props chain utilities
type PropValidation<T> = {
type?: PropType<T>;
required?: boolean;
default?: T | (() => T);
validator?: (value: T) => boolean;
};
// Template syntax type utilities
type BooleanPropValue<T> = T extends boolean ? T : boolean;
type ShortBindValue<T> = T;
type VModelValue<T> = T;
// Syntax sugar combination types
type SugarProps<T> = {
[K in keyof T]: T[K] extends boolean
? BooleanPropValue<T[K]>
: ShortBindValue<T[K]>;
};Install with Tessl CLI
npx tessl i tessl/npm-unplugin-vue-macros