Vue 3 Single File Component (SFC) представляет собой формат
организации компонентов, в котором шаблон, логика и стили объединены в
одном файле с расширением .vue. Такой подход тесно
интегрирован с инструментом сборки Vite, где обработка SFC выполняется
через @vitejs/plugin-vue, обеспечивая мгновенную
трансформацию, HMR и оптимизацию на уровне модулей.
Типичный SFC состоит из трёх основных блоков:
<template>
<div class="counter">
{{ count }}
</div>
</template>
<script>
export default {
data() {
return {
count: 0
}
}
}
</script>
<style scoped>
.counter {
font-size: 20px;
}
</style>
В таком виде компонент уже функционален, однако классический API
Options API постепенно уступает место Composition API и более
современному синтаксису script setup.
<script setup> — это синтаксический сахар над
Composition API, который упрощает структуру компонента и устраняет
необходимость явного return в setup().
Базовый пример:
<template>
<div>
{{ count }}
</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
Ключевые особенности:
setup() функцииComposition API используется напрямую:
<script setup>
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(2)
const total = computed(() => price.value * quantity.value)
</script>
В шаблоне .value не требуется:
<template>
<div>{{ total }}</div>
</template>
Vue 3 предоставляет специальные макросы, которые обрабатываются компилятором.
<script setup>
const props = defineProps({
title: String,
count: Number
})
</script>
Использование:
<template>
<h1>{{ title }}</h1>
</template>
<script setup>
const emit = defineEmits(['increment'])
function handleClick() {
emit('increment')
}
</script>
<template>
<button @click="handleClick">+</button>
</template>
Vite использует ESM-ориентированную архитектуру, что позволяет:
.vue файлы по требованию@vitejs/plugin-vue выполняет компиляцию SFC в JavaScript
модули, где:
Обычный scoped CSS:
<style scoped>
.button {
background: blue;
color: white;
}
</style>
Scoped стили реализуются через добавление уникальных атрибутов:
<div class="button" data-v-123abc></div>
Это обеспечивает изоляцию стилей между компонентами без BEM или ручных соглашений.
Поддерживается также подход CSS Modules:
<style module>
.button {
background: green;
}
</style>
Использование в script:
<template>
<button :class="$style.button">OK</button>
</template>
Одной из наиболее мощных возможностей Vue SFC является интеграция
JavaScript значений непосредственно в CSS через v-bind.
<script setup>
import { ref } from 'vue'
const color = ref('red')
</script>
<template>
<div class="box">Text</div>
</template>
<style scoped>
.box {
color: v-bind(color);
}
</style>
Значение color становится реактивным источником для CSS,
и при изменении переменной стили обновляются без ручного
вмешательства.
При компиляции Vite и Vue преобразуют v-bind() в CSS
переменные:
.box {
color: var(--v-color);
}
А в рантайме компонент получает инлайн-стили:
<div style="--v-color: red;"></div>
Это обеспечивает:
<script setup>
import { ref } from 'vue'
const width = ref('200px')
const radius = ref('12px')
</script>
<style scoped>
.card {
width: v-bind(width);
border-radius: v-bind(radius);
}
</style>
CSS v-bind может работать с computed значениями:
<script setup>
import { computed, ref } from 'vue'
const active = ref(true)
const themeColor = computed(() => active.value ? 'green' : 'gray')
</script>
<style scoped>
.panel {
background: v-bind(themeColor);
}
</style>
Несмотря на гибкость, существуют архитектурные ограничения:
<script setup>Inline styles:
<div :style="{ color: color }"></div>
CSS v-bind:
div {
color: v-bind(color);
}
Различия:
<script setup>
import { ref } from 'vue'
const size = ref(40)
const active = ref(false)
function toggle() {
active.value = !active.value
}
</script>
<template>
<button class="btn" @click="toggle">
Toggle
</button>
</template>
<style scoped>
.btn {
width: v-bind(size)px;
height: v-bind(size)px;
background: v-bind(active ? 'blue' : 'lightgray');
}
</style>
Такой подход демонстрирует плотную интеграцию логики и стилей без необходимости вычислять классы вручную.
Vite обеспечивает:
Благодаря этому CSS v-bind обновляется мгновенно без полной перезагрузки компонента, что особенно важно при работе с интерактивными UI системами.