Tổng hợp 64 câu hỏi phỏng vấn Vue.js kèm đáp án chi tiết, song ngữ Việt–Anh — sắp xếp từ cơ bản đến nâng cao. Ôn luyện miễn phí, tự động lưu tiến độ.
Vue.js là progressive JavaScript framework để xây dựng UI. (1) So với React: Vue có template syntax rõ ràng hơn, two-way binding tích hợp sẵn, learning curve thấp hơn; React dùng JSX, unidirectional flow, hệ sinh thái lớn hơn (2) So với Angular: Vue nhẹ…
Options API (Vue 2 style): tổ chức code theo loại (data, methods, computed, watch). Composition API (Vue 3): tổ chức code theo logic concern, dùng setup() hoặc <script setup. (1) Composition API dễ tái sử dụng logic hơn qua composables (2) TypeScript support tốt hơn…
<script setup là syntactic sugar cho Composition API — tất cả code bên trong tự động expose ra template mà không cần return. (1) Gọn hơn: không cần export default, không cần return (2) Hiệu năng tốt hơn: compiler tối ưu hoá tốt hơn (3)…
SFC (.vue file) gom template, script, style vào một file duy nhất — tiện lợi cho development. Cấu trúc: <template (HTML), <script setup (logic), <style scoped (CSS). (1) scoped attribute: CSS chỉ áp dụng cho component đó, tránh conflict (2) Compiler (Vite/webpack) parse và compile…
Vue directives là các HTML attribute đặc biệt gắn kết reactive behavior vào DOM. Phổ biến nhất: v-if/v-else/v-else-if: điều kiện render, xoá/tạo DOM thật. v-show: ẩn bằng display:none, DOM vẫn tồn tại. v-for: loop render, luôn cần :key. v-model: two-way binding cho input. v-bind (:attr):…
v-if: xoá hoàn toàn DOM khi false — chi phí cao khi toggle thường xuyên, nhưng không render child khi không cần (lazy). v-show: chỉ toggle display:none — DOM luôn được render, chi phí thấp khi toggle. Dùng v-show khi element cần toggle thường xuyên.…
Vue dùng :key để identify mỗi vnode khi diff — giúp tái sử dụng và reorder DOM nodes đúng cách thay vì re-render toàn bộ. (1) Thiếu key: Vue dùng "in-place patch" — có thể gây lỗi với stateful components hoặc animation (2) Dùng index…
v-model là shorthand: :modelValue + @update:modelValue. Mặc định cho input: Custom component v-model: Vue 3 hỗ trợ multiple v-model: v-model:title, v-model:content với props tương ứng.
Vue 3 dùng ES6 Proxy để intercept get/set operations trên reactive objects. Khi đọc property trong effect (computed, watcher, render): dependency được track. Khi set property: trigger cập nhật tất cả dependents. Cải tiến so với Vue 2 (dùng Object.defineProperty): (1) Detect thêm/xoá property động…
ref: wrap bất kỳ giá trị nào (primitives, objects) thành reactive container — truy cập qua .value trong script, tự unwrap trong template. reactive: wrap object/array thành reactive Proxy — truy cập trực tiếp, không cần .value. Khuyến nghị hiện tại (Vue 3.2+): Dùng ref…
computed: derive giá trị từ reactive state, kết quả được cache, chỉ recompute khi dependency thay đổi — dùng để transform/calculate data cho template. watch: observe cụ thể một hoặc vài sources, có access vào old/new value, lazy by default — dùng khi cần side…
Composable là function dùng Composition API để đóng gói và tái sử dụng stateful logic. Ví dụ: So với Mixins: (1) Không có naming collision — return value rõ ràng (2) Source rõ ràng — biết data từ đâu (3) Có thể nhận arguments (dynamic)…
Trong <script setup, lifecycle hooks được import và dùng như functions: Mapping từ Options API (bao gồm Vue 2 → Vue 3): beforeCreate/created → code trong setup() chạy thay thế, mounted → onMounted, updated → onUpdated, beforeUpdate → onBeforeUpdate, unmounted → onUnmounted, beforeMount → onBeforeMount.…
provide / inject cho phép truyền data qua component tree mà không cần props drilling. Parent provide, bất kỳ descendant nào có thể inject: Dùng khi: (1) Shared state cho subtree (theme, locale, auth) (2) Plugin/library cung cấp context. Lưu ý: khó debug hơn props…
defineProps khai báo props mà component nhận, defineEmits khai báo events mà component emit: Lưu ý: defineProps không thể destructure trực tiếp mà giữ reactivity trong Vue 3.4 trở về trước — dùng toRefs(props). Từ Vue 3.5+: destructure props với const { title } =…
Vue components giao tiếp qua nhiều cơ chế tuỳ quan hệ và chiều dữ liệu. (1) Props (parent → child): dữ liệu đi xuống, one-way (2) Emits (child → parent): event đi lên, gọi emit() (3) v-model: two-way binding, kết hợp props + emits (4)…
Slots cho phép parent inject content vào template của child component. Default slot: <slot /. Named slots: <slot name="header" / — parent dùng <template header. Scoped slot: child truyền data lên parent qua slot: Dùng scoped slots khi child biết cách lấy data nhưng parent…
Trong <script setup, component instance mặc định không expose properties ra ngoài (không access được qua template ref). defineExpose cho phép explicitly expose các methods/properties để parent gọi qua ref. Ví dụ: defineExpose({ focus, reset }) — parent gọi childRef.value.focus(). Dùng khi cần imperative control…
Vue Router là official router cho Vue.js — quản lý navigation, URL history, route matching. Navigate: <RouterLink to="/about" trong template, hoặc router.push('/about') trong script. <RouterView / là nơi component được render.
Navigation guards cho phép control navigation — xác thực, redirect, cancel. In-component guards (Options API): beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave. Trong Composition API dùng onBeforeRouteLeave, onBeforeRouteUpdate. Return false để cancel, return route location để redirect, return undefined/true để proceed.
Dynamic segment: path: '/user/:id' — đọc qua route.params.id. Lazy loading với dynamic import: Lazy loading: component chỉ được download khi navigate đến route đó — giảm initial bundle size. Lưu ý: / webpackChunkName / là Webpack magic comment, không có tác dụng trong Vite. Lưu…
Pinia là official state management library cho Vue 3 — thay thế Vuex. Ưu điểm: (1) Composition API-friendly, không cần mutations (2) TypeScript support tốt hơn nhiều (3) Không có nested modules, mỗi store là một module độc lập (4) Bundle nhỏ hơn (~1KB) (5)…
Pinia stores được tạo với defineStore() dùng setup-store syntax (khuyến nghị), trả về refs cho state, computed getters, và action functions. Lưu ý: destructure store mất reactivity — dùng storeToRefs: const { count, double } = storeToRefs(store) (methods thì destructure thường).
Pinia store là reactive object — destructuring trực tiếp sẽ mất reactivity (tương tự reactive()). storeToRefs() convert state và getters thành refs để destructure an toàn: const { count, name } = storeToRefs(store). Methods (actions) không cần storeToRefs — destructure thường: const { increment }…
v-memo skip re-render một subtree nếu array dependency không thay đổi — tương tự React.memo nhưng ở template level: Dùng cho: (1) Long lists với expensive child renders (2) Chỉ một vài properties ảnh hưởng đến render. Lưu ý: không lạm dụng — dependency array…
<KeepAlive cache component instance khi unmount — state được giữ nguyên khi switch lại: Lifecycle hooks cho cached components: onActivated (khi cache hit, component show lại), onDeactivated (khi bị hide, không unmount). Dùng cho: tab views, multi-step forms, expensive components cần giữ state. Lưu ý:…
Dùng dynamic import để lazy load component — chỉ download khi cần: Kết hợp với <Suspense để handle loading state elegantly.
Vue cung cấp error boundary mechanism qua errorCaptured (Options API) / onErrorCaptured (Composition API): Global handler: app.config.errorHandler = (err, instance, info) = { ... }. Error types caught: lifecycle hooks, event handlers, async errors trong setup, child component errors. Lưu ý: không catch errors trong…
Vue components được test bằng cách mount chúng với @vue/test-utils và assert trên rendered output và emitted events, dùng Vitest làm test runner. Dùng shallowMount để stub child components. Test behavior, không test implementation details.
Vue batch DOM updates — không update ngay khi state thay đổi, mà queue updates và flush async. nextTick cho phép chờ DOM được update xong: Dùng khi: (1) Cần đọc DOM sau khi state update (2) Focus element sau khi v-if toggle (3) Scroll…
toRef: tạo ref từ một property của reactive object — giữ reactive connection: toRefs: convert toàn bộ reactive object thành object of refs — dùng khi destructure: toValue (Vue 3.3+): unwrap ref hoặc getter — dùng trong composables để accept cả ref và plain value:
Vue a11y best practices theo chuẩn ARIA và semantic HTML, kết hợp Vue-specific tooling như vue-axe và eslint-plugin-vuejs-accessibility để phát hiện vấn đề sớm. (1) Dùng semantic HTML trong templates (<button không phải <div @click) (2) :aria-label, :aria-expanded, :aria-live với dynamic content (3) Focus management…
Template ref cho phép truy cập DOM element hoặc component instance trực tiếp: Lưu ý: ref.value là null trước khi component mount — luôn kiểm tra trong onMounted hoặc dùng optional chaining ref.value?.method().
Pattern chuẩn để fetch async data trong Vue 3 Composition API là dùng onMounted với try/catch/finally, hoặc trích xuất thành composable tái sử dụng. Lưu ý: không gọi async setup() trực tiếp mà không có <Suspense bọc ngoài — dùng onMounted hoặc composable thay. Với…
Vue tự động unwrap refs trong một số contexts — hiểu rõ để tránh bugs: Template auto-unwrap: refs được auto-unwrap trong template, không cần .value: Reactive object unwrap: ref là property của reactive object được tự động unwrap khi access: Không unwrap: ref trong array…
Route meta cho phép đính kèm custom data vào routes — thường dùng cho auth, breadcrumbs, page titles: Lưu ý: to.meta tổng hợp metadata từ tất cả matched routes (parent + child) — child ghi đè parent.
Vue Router cho phép kiểm soát scroll behavior khi navigate: Dùng savedPosition để implement proper back/forward scroll restoration — trải nghiệm native-like.
Dùng InjectionKey để provide/inject type-safe, tránh string key collisions: Dùng Symbol làm key thay vì string để tránh naming collision trong large apps hoặc libraries.
v-once: render element/component một lần duy nhất — skip future updates. Sau khi render, element được xử lý như static content: v-pre: skip compilation toàn bộ subtree — dùng cho content muốn hiển thị mustache syntax như raw text: Khác nhau: v-once render rồi freeze…
Built-in modifiers: - .lazy: sync sau change event thay vì input — giảm updates - .number: auto convert sang number (tương đương parseFloat) - .trim: auto trim whitespace Custom modifiers cho component v-model:
Vì trong Vue 3, v-if có độ ưu tiên cao hơn v-for — điều kiện được đánh giá trước, nên nó không nhìn thấy biến của vòng lặp. Đoạn dưới ném lỗi vì user chưa tồn tại ở thời điểm v-if chạy: Hai cách sửa:…
Vue áp dụng one-way data flow: props chỉ truyền từ cha xuống con. Gán props.title = ... sẽ bị Vue cảnh báo (và ở chế độ dev là lỗi) vì mỗi lần cha re-render, giá trị đó bị ghi đè lại — sửa ở con…
Vì reactive() trả về một Proxy — reactivity nằm ở thao tác truy cập thuộc tính qua proxy, không nằm trong giá trị. Destructure lấy ra giá trị nguyên thuỷ tại thời điểm đó, cắt đứt liên kết với proxy: Cách giữ liên kết: Với…
Ba điểm hay vướng khi watch dữ liệu dạng object: 1. deep. watch một ref chứa object chỉ chạy khi thay cả object (obj.value = {...}). Đổi thuộc tính bên trong thì không kích hoạt — trừ khi bật { deep: true }. Riêng khi…
defineModel() là macro (ổn định từ Vue 3.4) gói lại đúng cặp prop + emit mà trước đây phải khai báo tay, và trả về một ref hai chiều. Khác biệt đáng nói: - Ghi model.value = x sẽ tự emit update:modelValue; đọc model.value lấy…
Setup store dùng đúng cú pháp setup(): ref là state, computed là getter, function là action. Cuối hàm phải return những gì muốn công khai. So với option store ({ state, getters, actions }): - Linh hoạt hơn: dùng được watch, composable khác, hoặc tạo…