Junior: питання на співбесіді з теми «TypeScript та інструменти»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
4 питання
Однофайловий компонент (SFC, файл .vue) об'єднує в одному файлі три частини:
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">Натиснуто {{ count }} разів</button>
</template>
<style scoped>
button { font-weight: 600; }
</style>
<script>- логіка компонента;<template>- розмітка, яку компілятор перетворює на функцію рендеру;<style>- стилі; зscopedвони діють лише на цей компонент.
Браузер не розуміє .vue-файлів - їх компілює збирач (Vite з плагіном @vitejs/plugin-vue).
<script setup> - скорочений запис Composition API. Без нього довелося б писати:
export default {
setup() {
const count = ref(0)
return { count } // усе, що потрібно шаблону, - вручну
},
}
Що дає <script setup>:
- усе оголошене на верхньому рівні доступне в шаблоні - змінні, функції, імпортовані компоненти. Не треба повертати об'єкт і реєструвати компоненти в
components; - макроси компілятора
defineProps,defineEmits,defineModel,defineExpose- їх не імпортують, компілятор замінює їх на опції компонента; - кращі типи: props і події описуються типами TypeScript;
- продуктивніший код: шаблон компілюється в ту саму область видимості, що й скрипт, без проміжного проксі.
Що варто знати:
- компонент з
<script setup>за замовчуванням закритий: батьківський компонент через ref шаблону не бачить його внутрішніх змінних. Відкрити частину -defineExpose({ reset }); - код
<script setup>виконується для кожного екземпляра компонента, а звичайний<script>поруч - один раз при імпорті модуля (там зручно оголошувати типи й константи).
Офіційний спосіб створити проєкт - утиліта create-vue:
npm create vue@latest
Вона запитає, що додати: TypeScript, Vue Router, Pinia, Vitest, Playwright, ESLint, Prettier. Результат - проєкт на Vite з готовими налаштуваннями.
Що робить Vite:
- під час розробки (
npm run dev) віддає модулі браузеру майже як є, а.vue-файли компілює на льоту плагіном@vitejs/plugin-vue: шаблон - у функцію рендеру,<script setup>- у звичайний компонент, стилі - у CSS. Зміна компонента оновлюється через гарячу заміну модулів (HMR) зі збереженням стану; - для продакшену (
npm run build) збирає, мініфікує, розділяє код на частини й додає хеші в імена файлів.
TypeScript у Vite лише прибирає типи (транспіляція), але не перевіряє їх - заради швидкості. Перевірку робить окрема команда:
"scripts": {
"dev": "vite",
"build": "vue-tsc --build && vite build",
"type-check": "vue-tsc --build"
}
vue-tsc - обгортка над tsc, що розуміє .vue-файли. Звичайний tsc їх не бачить.
У Laravel-проєкті Vue підключають до вже наявного Vite:
// vite.config.js
import laravel from 'laravel-vite-plugin'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [
laravel({ input: 'resources/js/app.ts', refresh: true }),
vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false } } }),
],
})
Опції transformAssetUrls потрібні, щоб шляхи до зображень у шаблонах (/images/logo.png) вели на файли Laravel у public, а не перетворювалися на імпорти. Стартові набори Laravel (Vue + Inertia) мають усе це налаштованим.
Редактор: розширення Vue - Official (колишній Volar) для VS Code дає підсвітку, автодоповнення й перевірку типів у шаблонах.
Оголошення через тип - найзручніший спосіб у <script setup lang="ts">:
<script setup lang="ts">
interface Props {
title: string
count?: number
tags?: string[]
}
const props = defineProps<Props>()
</script>
Компілятор сам перетворює тип на runtime-оголошення (title: { type: String, required: true }), тож Vue перевіряє props і під час виконання в режимі розробки.
Значення за замовчуванням - два способи:
1. Деструктуризація props (Vue 3.5+):
const { title, count = 0, tags = () => [] } = defineProps<Props>()
Змінні, отримані деструктуризацією defineProps, лишаються реактивними: компілятор замінює звернення count на props.count. Але є нюанс - передати таку змінну у watch чи composable напряму не можна, лише як геттер:
watch(() => count, (value) => { /* ... */ }) // правильно
watch(count, ...) // помилка компіляції
useSomething(() => count)
2. withDefaults (до 3.5 і досі підтримується):
const props = withDefaults(defineProps<Props>(), {
count: 0,
tags: () => [],
})
Значення-об'єкти й масиви задаються функцією, що повертає нове значення, інакше всі екземпляри компонента ділили б один масив.
Обмеження оголошення через тип:
- тип має бути описаний у файлі чи імпортований з відносного шляху або пакета - компілятор аналізує його статично. Дуже складні умовні типи він не розбере;
- runtime-перевірка бачить лише базові типи (
String,Array), а не вмістstring[]- глибока перевірка лишається за TypeScript.
Не змінювати props усередині компонента. props.title = 'x' - попередження Vue: дані йдуть від батька до дитини, а зміни - назад через події чи defineModel.
Vue DevTools - інструмент налагодження Vue-застосунків. Доступний як розширення браузера та як плагін Vite (vite-plugin-vue-devtools), що вбудовує панель прямо в сторінку під час розробки.
Що в ньому корисно:
1. Дерево компонентів. Ієрархія компонентів сторінки, як вона є в застосунку, а не в DOM. Для обраного компонента видно:
- props, які він отримав;
- внутрішній стан (
ref,reactive,computed) - значення можна змінювати на льоту й одразу бачити результат; - події, які він випромінює.
Клік по елементу сторінки в режимі вибору показує, який компонент його відрендерив і в якому файлі він лежить.
2. Pinia. Стан кожного стору, геттери, і історія змін з можливістю повернутися до попереднього стану (time travel). Видно, яка дія що змінила.
3. Vue Router. Поточний маршрут, параметри, список маршрутів, історія переходів.
4. Хронологія (Timeline). Події компонентів, дії Pinia, переходи маршрутизатора, а також рендери й оновлення з тривалістю. Тут видно, який компонент перерендерюється частіше, ніж мав би.
5. Продуктивність. Час рендеру й оновлення кожного компонента - перша зупинка, коли інтерфейс гальмує.
Що варто знати:
- у продакшен-збірці DevTools за замовчуванням вимкнені: Vue прибирає службовий код для них, і розширення нічого не бачить. Це правильно - не вмикайте їх на продакшені без потреби;
- з
<script setup>компоненти показуються з назвою файлу; для анонімних компонентів назву можна задати черезdefineOptions({ name: 'OrderCard' }); - для Inertia-застосунків на Laravel DevTools працюють так само: сторінки Inertia - звичайні Vue-компоненти.
Порядок налагодження «чому не оновлюється»: подивитися в DevTools, чи змінився стан. Якщо змінився, а екран ні - проблема в рендері (ключі, реактивність). Якщо не змінився - у логіці, що мала його змінити.