Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

  • Start Date: 2025-08-27
  • Target Major Version: 3.x
  • Reference Issues:
  • Implementation PR:

Summary

Introduce a concise way to define local/micro components within another component file, without requiring JSX/TSX.

Basic example

Doesn't have to be exactly this, this is just a general idea of how it could be:

const MyButton = defineLocalComponent(({ props, emit }) =>
  <template>
    <button @click="emit('click')">{{ props.count }}</button>
  </template>
)

Motivation

Developers often encounter “micro-components” - Template code that are:

  • Too small to create their own .vue file.
  • Reusable enough that duplication feels wrong.

Currently the only way to achieve this is using JSX and h() calls

  • But, JSX, h() calls are verbose and difficult to read.
  • Also, JSX requires extra tooling that some teams avoid.

Detailed design

Here is an example of a practical use case of this feature. Let us assume we are creating a button with inline icon:

<template>
  <div>
    <button class="icon-btn" @click="() => {}">
      <i class="fa fa-plus"></i>
      Add
    </button>

    <button class="icon-btn" @click="() => {}">
      <i class="fa fa-trash"></i>
      Delete
    </button>
  </div>
</template>

In this example, most of the code is duplicate but also:

  • Too small to create their own .vue file.
  • Reusable enough that duplication feels wrong.

This problem could be solved by defining micro-component locally within the file. The code would then look something like this:

<script setup>
const IconButton = defineLocalComponent(({ props, emit }) =>
  <button @click="emit('click')" class="icon-btn">
    <i :class="props.icon"></i>
    {{ props.label }}
  </button>
)
</script>

<template>
  <div>
    <IconButton icon="fa fa-plus" label="Add" @click="() => {}" />
    <IconButton icon="fa fa-trash" label="Delete" @click="() => {}" />
  </div>
</template>

Drawbacks

  • Requires compiler level changes that works for build-time as well as run-time

Alternatives

JSX and h() calls.

  • But, JSX, h() calls are verbose and difficult to read.
  • Also, JSX requires extra tooling that some teams avoid.

Adoption strategy

There will be no breaking changes. Developers can adopt to new or existing Vue 3 codebase without breaking anything.

Unresolved questions

  • Should the local components only support props and emits?
You must be logged in to vote

Replies: 2 comments

Comment options

Why not just support multiple components in a SFC file? In this way a main component and related components can be co-located and managed more easily and make use of compiler macros. I find the single component per file restriction strange.

<component name="C1">
	<script setup></script>
	<template></template>
	<style></style>
</component>
<component name="C2">
	<script setup></script>
	<template></template>
	<style></style>
</component>
...

then

import {C1, C2} from "file1.vue"
You must be logged in to vote
0 replies
Comment options

Not official but we have https://vue-vine.dev ~ it's compatible with SFC and you can leverage more flexibility and write multiple components in one TS file.

The Vue Vine toolchain is backed by Vue official members like @johnsoncodehk and more vue core members, if you meet any issue please report to https://github.com/vue-vine/vue-vine/issues ❤️

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.