Frontend Development 19 min read

Comprehensive Guide to Vue Component Writing Styles: Options API, Composition API, Setup Syntax Sugar, Render Functions, and JSX

This article systematically introduces the many ways to write Vue components—including the classic Options API, the modern Composition API with setup syntax sugar, hand‑written render functions using h or createVNode, and various JSX techniques—explaining their principles, code examples, and when to choose each approach.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Comprehensive Guide to Vue Component Writing Styles: Options API, Composition API, Setup Syntax Sugar, Render Functions, and JSX

Introduction

Vue 3’s official documentation mentions two primary component styles: the Options API and the Composition API. In practice, Vue components can be written in many more ways, all built on the same underlying system. Understanding these styles helps you read the docs, interpret ambiguous APIs, and explore Vue’s source code.

Setup Syntax Sugar

The setup syntax sugar is the most common pattern in Vue 3. A component is placed in a single .vue file with <template> , <script setup> , and <style> sections. The example below shows a simple component that defines a ref and renders it.

<template>
  <div>{{ name }}</div>
</template>

<script setup lang="ts">
import { ref } from "vue";
const name = ref("天气好");
</script>

<style scoped></style>

In App.vue the component is imported and used like any other component.

// App.vue
<template>
  <User />
</template>

<script setup lang="ts">
import User from "./User.vue";
</script>

<style scoped></style>

Vue 2 Options‑style Writing

Classic Options API

The classic Vue 2 style exports a plain object containing data , methods , etc.

<template>
  <div>{{ name }}</div>
</template>

<script lang="ts">
export default {
  data: () => ({
    name: "天气好"
  })
};
</script>

<style></style>

defineComponent Helper

Using defineComponent provides better type inference while still exporting a plain object.

<template>
  <div>{{ name }}</div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  data: () => ({
    name: "天气好"
  })
});
</script>

<style></style>

Vue 3 Options‑style Writing

Vue 3 introduces a new setup option inside the Options API, allowing the use of Composition API features such as ref and reactive while keeping the familiar data / methods structure.

<template>
  <div>{{ name }}</div>
</template>

<script lang="ts">
export default {
  setup() {
    return { name: "天气好" };
  }
};
</script>

<style></style>

When defineComponent is used, the setup parameters are typed, improving IDE support.

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  setup(props, context) {
    return { name: "天气好" };
  }
});
</script>

Hand‑written Render Functions

Templates are compiled to render functions. You can bypass the template and write a render function directly, using either h (alias of createVNode ) or JSX.

<script lang="ts">
import { defineComponent, h } from "vue";
export default defineComponent({
  data: () => ({ name: "天气好" }),
  render() {
    return h("div", this.name);
  }
});
</script>

Setup Returning a Render Function

Instead of returning an object for the template, setup can return a render function.

<script lang="ts">
import { defineComponent, h, ref } from "vue";
export default defineComponent({
  setup() {
    const name = ref("天气好");
    return () => h("div", name.value);
  }
});
</script>

Note that ref values must be accessed via .value inside h because automatic unwrapping only works in templates.

Using JSX

JSX inside a render function

JSX can replace h for a more concise syntax.

<script lang="tsx">
import { defineComponent } from "vue";
export default defineComponent({
  data() { return { name: "天气好" }; },
  render() {
    return (<>
{this.name}
);
  }
});
</script>

JSX returned from setup

<script lang="tsx">
import { defineComponent, ref } from "vue";
export default defineComponent({
  setup() {
    const name = ref("天气好");
    return () => (<>{name.value});
  }
});
</script>

Directly exporting a JSX object

You can export a JSX element directly, which is useful for tiny reusable pieces.

<script lang="tsx">
import { ref } from "vue";
const name = ref("天气好");
const User = <>{name.value};
export default User;
</script>

Functional Components (FC)

Vue allows function‑style components that receive props as arguments.

<script lang="tsx">
import { ref } from "vue";
export default function User(props: { "user-name": string }) {
  const name = ref("天气好");
  return <>{props["user-name"]};
}
</script>

Standalone JSX/TSX Files

All the above patterns can be placed in .tsx files without the surrounding <script> block, making them look more like pure JSX components.

// User.tsx
import { ref, defineComponent } from 'vue';
export default defineComponent({
  setup() {
    const name = ref('天气好');
    return () => (<>{name.value});
  }
});

Functional components can also be written as plain functions and exported directly.

// User.tsx
import { ref } from 'vue';
export default function User(props) {
  const name = ref('天气好');
  return <>{props.userName};
}
User.props = { userName: String };

Conclusion

Vue’s core remains option‑based, but Vue 3 adds the setup option and syntax sugar, allowing most logic to live inside setup . While templates are the recommended way to describe UI, hand‑written render functions and JSX give you fine‑grained control when needed.

Personal Opinion

Prefer the setup syntax sugar for new code.

When using the Options API, wrap the component with defineComponent for better type inference.

If JSX is required, use the Options API with setup returning a JSX render function inside a .vue file rather than moving the component to a separate .tsx file.

For extensive functional‑component use, consider React instead of Vue.

References

Rendering Functions & JSX | Vue.js

frontendJavaScriptComponentVueJSXSetupRender Function
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.