SFC 作成規則
10.4.1. ブロック順序
SFC(Single File Component) 内のブロックは以下の順序に従います。
<script setup lang="ts">— ロジック<template>— マークアップ<style scoped>— スタイル
vue
<script setup lang="ts">
import { ref } from 'vue'
const message = ref('Hello')
</script>
<template>
<p>{{ message }}</p>
</template>
<style scoped>
p {
color: inherit;
}
</style>必須
ESLint vue/block-order ルールがこの順序を強制します。違反した場合、リントエラーが発生します。
10.4.2. template 作成規則
v-htmlは使用しません。 XSS 攻撃に脆弱です。やむを得ない場合は DOMPurify でサニタイズした後に使用します。v-forには必ず:keyをバインドします。indexを key として使用しません。v-ifとv-forを同じ要素に同時に使用しません。<template>タグで分離します。
vue
<!-- 正しい例 -->
<template v-for="item in items" :key="item.id">
<div v-if="item.isActive">
{{ item.name }}
</div>
</template>
<!-- 誤った例 -->
<div v-for="item in items" v-if="item.isActive" :key="item.id">
{{ item.name }}
</div>10.4.3. 属性バインディング規則
- 静的属性は通常の HTML 属性として、動的属性は
v-bind(:) 省略記法で記述します。 - boolean 属性は値なしで宣言して
trueを渡します。 - 属性が3つ以上の場合、1行に1つずつ配置します。
vue
<!-- 属性が3つ以上 — 1行に1つずつ -->
<UserCard
:user="currentUser"
:editable="isAdmin"
:loading="isLoading"
@update="handleUpdate"
/>
<!-- boolean 属性 -->
<BaseButton
primary
disabled
@click="handleClick"
/>10.4.4. イベントハンドリング
- イベントハンドラーは
@省略記法を使用します。v-onは使用しません。 - インラインハンドラーは単純な式(1行)にのみ許容します。
- 複雑なロジックは別の関数に分離します。
vue
<script setup lang="ts">
function handleSubmit() {
// 複雑なロジック
}
</script>
<template>
<!-- 正しい例: 単純な式 -->
<button @click="count++">増加</button>
<!-- 正しい例: 関数参照 -->
<form @submit.prevent="handleSubmit">
<!-- ... -->
</form>
</template>10.4.5. style 規則
<style>タグには必ずscopedを使用します。グローバルスタイルはsrc/styles/ディレクトリで管理します。:deep()セレクターは子コンポーネントのスタイルオーバーライド時にのみ限定的に使用します。- Tailwind CSS ユーティリティクラスを優先的に使用し、カスタム CSS は最小限にします。
vue
<style scoped>
/* scoped スタイル */
.container {
@apply flex items-center gap-4;
}
/* 子コンポーネントのスタイルオーバーライド(限定的に許容) */
:deep(.child-class) {
color: inherit;
}
</style>