面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

服务端阅读 05月29日 01:55

Canvas 动画怎么实现?如何优化性能?

Canvas 动画本质是逐帧重绘:每帧调用 requestAnimationFrame 回调,在其中更新状态、清除画布、重绘所有元素,浏览器按刷新率(通常 60fps)将帧提交到屏幕。性能优化的核心思路是减少每帧的计算量和绘制量:用 OffscreenCanvas + Worker 将计算和预渲染移到后台线程;用对象池复用粒子避免 GC 压力;用脏矩形只重绘变化区域;分层 Canvas 将静态背景和动态前景分离;批量绘制减少状态切换。追问requestAnimationFrame 和 setInterval 做动画有什么本质区别?OffscreenCanvas 在 Worker 中如何与主线程 Canvas 同步?对象池模式怎么实现?复用对象时要注意清理哪些字段?什么是脏矩形优化?在什么场景下效果明显?分层 Canvas 的代价是什么?层太多反而更慢吗?写段代码// 离屏预渲染 + requestAnimationFrameconst offscreen = new OffscreenCanvas(60, 60)const offCtx = offscreen.getContext('2d')offCtx.fillStyle = 'coral'offCtx.beginPath()offCtx.arc(30, 30, 25, 0, Math.PI * 2)offCtx.fill()let x = 0function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height) ctx.drawImage(offscreen, x, 100) x = (x + 2) % canvas.width requestAnimationFrame(animate)}animate()
服务端阅读 05月29日 01:55

Canvas 元素是什么?和 SVG 有什么区别?

Canvas 是 HTML5 的 <canvas> 元素,提供一块可编程的像素级绘图表面。通过 JS 获取 2D 渲染上下文(getContext('2d'))或 WebGL 上下文来绘制图形。核心用途:数据可视化、2D 游戏、图像处理、动画、视频特效。与 SVG 的关键区别:Canvas 是栅格模式(像素绘制,适合高频更新和大量对象),SVG 是矢量模式(DOM 节点,适合交互和缩放)。Canvas 不保留绘制对象,每帧是完整重绘。追问Canvas 2D 和 WebGL 上下文有什么区别?什么场景需要用 WebGL?Canvas 重绘时旧内容去哪了?为什么说 Canvas 是"立即模式"渲染?Canvas 如何实现像素级操作?getImageData 和 putImageData 的性能如何?Canvas 的 width/height 属性和 CSS 宽高不一致时会怎样?什么情况下应该选 SVG 而不是 Canvas?写段代码const canvas = document.querySelector('canvas')canvas.width = 400 // 设置分辨率canvas.height = 300const ctx = canvas.getContext('2d')ctx.fillStyle = '#4a90d9'ctx.fillRect(10, 10, 100, 80) // 绘制矩形ctx.font = '16px sans-serif'ctx.fillText('Hello Canvas', 120, 50) // 绘制文字
服务端阅读 05月29日 01:55

Canvas 路径绘制和图形变换怎么用?

路径绘制分三步:定义路径、闭合路径、渲染路径。先用 beginPath() 清除旧路径,moveTo() 定起点,再用 lineTo()/arc()/bezierCurveTo() 等绘制子路径,最后 closePath() 闭合并用 fill() 或 stroke() 渲染。图形变换通过坐标系变换实现:translate(x,y) 平移原点、rotate(angle) 绕原点旋转、scale(sx,sy) 缩放,transform(a,b,c,d,e,f) 直接设置变换矩阵。变换是累积的,用 save()/restore() 管理状态栈,避免污染后续绘制。追问beginPath() 和 closePath() 的区别是什么?不调用 closePath() 会怎样?save()/restore() 保存了哪些状态?变换矩阵和路径都会保存吗?transform() 和 setTransform() 有什么区别?多次 translate() 后坐标系如何变化?如何回到初始状态?如何用贝塞尔曲线绘制平滑曲线?控制点怎么选?写段代码ctx.save()ctx.translate(150, 150) // 移动原点到画布中心ctx.rotate(Math.PI / 6) // 旋转30度ctx.fillStyle = 'tomato'ctx.fillRect(-40, -40, 80, 80) // 以新原点为中心绘制ctx.restore() // 恢复原始坐标系
服务端阅读 05月29日 01:55

Nuxt.js 的路由系统和 Vue Router 有什么不同?

核心区别:Vue Router 需要手动在 router.ts 中声明路由表(path/component 映射);Nuxt 基于文件系统自动生成路由——pages/ 目录的文件路径即路由路径。例如 pages/user/[id].vue 自动映射为 /user/:id,pages/user/index.vue 映射为 /user。Nuxt 还内置了 layouts/ 布局系统、middleware/ 路由中间件(替代 Vue Router 的 beforeEnter/全局守卫),以及 NuxtPage 和 NuxtLayout 组件处理嵌套路由渲染。底层仍使用 Vue Router,但零配置。追问Nuxt 的嵌套路由怎么定义?和 Vue Router 的 children 有什么对应关系?路由中间件的执行顺序是什么?全局、布局、页面级中间件谁先执行?动态路由 [id].vue 在 SSG 模式下需要额外配置吗?如何在 Nuxt 中自定义 Vue Router 的 scrollBehavior?Nuxt 3 的 typedPages 实验特性是做什么的?写段代码<!-- pages/user/[id].vue --><script setup>definePageMeta({ middleware: 'auth', layout: 'dashboard'})const route = useRoute()const id = route.params.id</script>
服务端阅读 05月29日 01:55

Nuxt.js 中如何管理状态?useState 和 Pinia 怎么选?

Nuxt 3 推荐两种方案:内置的 useState() composable 和 Pinia(通过 @pinia/nuxt 模块集成)。useState() 适合跨组件共享简单响应式状态,天然 SSR 安全——服务端和客户端状态自动同步,无需额外处理水合。Pinia 适合复杂状态管理,支持 actions、getters、插件生态,且同样对 SSR 友好。Vuex 是 Nuxt 2 时代的默认方案,Nuxt 3 已不再内置。追问useState() 和 ref() 在 SSR 场景下有什么区别?为什么不能用 ref() 共享状态?Pinia store 在 Nuxt 3 中如何避免跨请求状态污染?useState() 的底层实现原理是什么?它是怎么保证 SSR 水合一致的?什么场景下 useState() 不够用,必须上 Pinia?Nuxt 3 的 useState() 可以在普通 JS 文件中使用吗?还是必须在 setup 中?写段代码// composables/useCounter.js - useState 方案export const useCounter = () => useState('counter', () => 0)// stores/user.js - Pinia 方案export const useUserStore = defineStore('user', () => { const user = ref(null) const login = async (creds) => { user.value = await $fetch('/api/login', creds) } return { user, login }})
服务端阅读 05月29日 01:55

Nuxt.js 的 SSG 和 SSR 有什么区别?怎么选?

SSG 在构建时(nuxt generate)遍历所有路由,执行数据获取逻辑,生成完整静态 HTML 文件,部署到任意静态服务器即可,请求零服务端开销;SSR 在每次请求时由 Node 服务动态渲染 HTML,内容实时但需要持续运行服务器。Nuxt 3 通过 routeRules 支持混合模式:同一个应用中,博客页 SSG、商品页 ISR(swr 缓存)、后台 SPA,按路由粒度选择渲染策略,不再需要二选一。追问ISR(Incremental Static Regeneration)在 Nuxt 3 里怎么实现?和 Next.js 的 ISR 有什么区别?SSG 构建时动态路由太多怎么办?如何按需生成?混合模式下 SSR 和 SSG 页面的 payload 传递机制有区别吗?SSG 页面的客户端数据怎么保持更新?Nitro 的预设(preset)对 SSG/SSR 部署有什么影响?写段代码// nuxt.config.ts - 混合渲染策略export default defineNuxtConfig({ routeRules: { '/': { prerender: true }, // SSG '/blog/**': { swr: 3600 }, // ISR 1小时 '/dashboard/**': { ssr: false }, // SPA '/api/**': { cors: true } // API路由 }, nitro: { preset: 'cloudflare-pages' }})
服务端阅读 05月29日 01:54

Nuxt.js 的模块和插件有什么区别?

模块(Module)在 Nuxt 初始化阶段执行,能修改构建配置、注册插件和中间件,是 Nuxt 核心扩展机制,通过 nuxt.config 的 modules 数组注册。插件(Plugin)在 Vue 实例化前后执行,用于注册全局组件、指令或注入实例属性,放在 plugins/ 目录自动注册。关键区别:模块可以注册插件,反过来不行;模块可发布为 npm 包(如 @nuxtjs/axios),插件通常项目内使用。追问模块的执行时机为什么比插件早?如果插件需要修改 Nuxt 配置怎么办?modules 数组中的顺序会影响什么?多个模块冲突如何处理?Nuxt 3 中模块和插件的注册方式有什么变化?如何编写一个可发布的 Nuxt 模块?需要导出什么?插件的 mode 属性(client/server)在 Nuxt 3 中被什么替代了?写段代码// nuxt.config.js - 注册模块和插件export default { modules: ['@pinia/nuxt', '@nuxtjs/i18n'], plugins: ['~/plugins/vue-gtag.client.js']}// plugins/vue-gtag.client.jsexport default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.use(VueGtag, { config: { id: 'G-XXX' } })})
服务端阅读 05月29日 01:54

Nuxt.js 应用性能优化有哪些关键手段?

Nuxt 性能优化分三层:构建层利用 Nitro 做 payload 提取,将 SSR 数据抽到独立 JSON 避免重复内联;渲染层通过 routeRules 按Route规则混合 SSR/SSG/SPA,静态页面用 prerender 避免运行时渲染开销;资源层用 @nuxt/image 自动生成响应式 srcset 和 WebP 格式,LazyHydrate 延迟水合非首屏组件。此外 Nuxt 3 基于 Vite 的按需编译和 tree-shaking 本身就比 Nuxt 2 的 Webpack 产物更小。追问payload extraction 具体做了什么?对 TTFB 有多大影响?@nuxt/image 的 ipx 服务是做什么的?和直接用 CDN 图片处理有什么区别?Nuxt 3 的 LazyHydrate 组件怎么用?和 Vue 的 Suspense 有什么关系?Nitro 的缓存策略(cachedFunctions)怎么配置?静态资源加 hash 缓存后,怎么处理版本更新问题?写段代码// nuxt.config.ts - 性能优化配置export default defineNuxtConfig({ modules: ['@nuxt/image'], routeRules: { '/blog/**': { swr: 3600 }, // ISR: 1小时缓存 '/admin/**': { ssr: false }, // SPA: 跳过SSR '/': { prerender: true } // SSG: 构建时生成 }, experimental: { payloadExtraction: true }})
服务端阅读 05月29日 01:54

Nuxt 3 有哪些数据获取方式?useFetch 和 useAsyncData 怎么选?

Nuxt 3 提供两个核心组合式函数:useFetch 和 useAsyncData。useFetch 是 useAsyncData + $fetch 的语法糖,99% 场景用 useFetch 即可;useAsyncData 适合需要自定义获取逻辑(如依赖多个 API 聚合数据)的场景。两者都在 SSR 时于服务端执行,结果序列化到 payload 中供客户端 hydration 复用,避免重复请求。底层 HTTP 客户端是 ofetch($fetch),支持服务端直接调用,无跨域问题。追问useFetch 的 key 是干什么用的?不写会怎样?SSR 时数据怎么从服务端传到客户端?hydration mismatch 怎么避免?$fetch 和 useFetch 的区别是什么?能不能在组件里直接用 $fetch?server/api 里的接口怎么和 useFetch 配合?如何给 useFetch 加请求缓存和去重?写段代码// 自定义 key + transformconst { data, pending } = await useFetch( `/api/user/${route.params.id}`, { key: `user-${route.params.id}`, transform: (res) => res.data, getCachedData(key, nuxt) { return nuxt.payload.data[key] } })
服务端阅读 05月29日 01:54

Nuxt.js 和普通 Vue 应用有什么区别?

Nuxt.js 是基于 Vue 的全栈框架,核心区别在于:普通 Vue 是纯客户端渲染 SPA,需要手动配置 Vue Router、Pinia、Vite 等生态;Nuxt 内置了 SSR/SSG/SPA 三种渲染模式、基于 pages/ 目录的文件路由、组件和组合式函数的自动导入、server/api 目录的 BaaS 风格服务端路由,以及 Nitro 服务引擎。普通 Vue 应用首屏为空壳 HTML,SEO 差;Nuxt 默认 SSR 可输出完整 HTML,对 SEO 和首屏性能更友好。追问Nuxt 3 的自动导入是怎么实现的?和手动 import 有什么性能差异?什么场景下应该选 SPA 模式而非 SSR?Nuxt 的 server/api 目录和传统后端 API 有什么区别?Nuxt 3 为什么用 Nitro 替代了 Nuxt 2 的服务端架构?如果项目从 Vue CLI 迁移到 Nuxt,最大的改造成本在哪?写段代码// nuxt.config.ts - 三种渲染模式切换export default defineNuxtConfig({ routeRules: { '/': { prerender: true }, // SSG '/api/**': { cors: true }, // 服务端路由 '/dashboard': { ssr: false } // SPA }})