Appearance
题面卡 · 问题对照
按** 怎么问**列卡。先看标题自己答,再点开对照「我的说法」。
链概念卡时用英文锚点,例如
/mine/explain#reflow-repaint(不要写#重排/重绘/合成,斜杠会跳飞)。
本页分段:浏览器与网络 · HTML · CSS · JavaScript · Vue 基础 · Vue3 基础 · UniApp · 架构 · 进阶 · 工程 · 实践 · 构建 · 追问 · 项目 · 实战
浏览器与网络
搜索引擎 / SEO
搜索引擎是怎么工作的?前端怎么做 SEO?
对上我的说法
→ 概念 · 搜索引擎 / SEO
建议答到的点
- 搜索引擎三步:抓取、索引、排名
- 爬虫看 HTML,不等于用户看到的渲染结果(SPA 单页应用空壳)
- 前端能做:SSR(服务端渲染)/ SSG(静态站点生成)/ 预渲染、语义化、title/description、sitemap(站点地图)、性能
常追问
- Vue / React SPA(单页应用)为什么不利于 SEO?怎么解? → 概念卡 · SPA 怎么解
答到:CSR 空壳;解法是 HTML 里先有正文(SSR / SSG / 预渲染,不是只有 SSR);已有 Vite + Vue 官网优先 History + 预渲染公开页 - 官网为啥不要用 Hash 路由? → Hash / History 题
- 语义化标签怎么帮索引? → HTML 语义化题
百科对照(可选)
→ 搜索引擎与 SEO
XSS / CSRF
什么是 XSS 和 CSRF?如何预防?
对上我的说法
→ 概念 · XSS / CSRF
建议答到的点
- XSS(跨站脚本):往页面注入并执行恶意脚本
- CSRF(跨站请求伪造):借已登录的 Cookie 冒充你发请求
- 两者区别,以及各自怎么防
常追问
- 存储型 / 反射型 / DOM 型 XSS 差在哪?
- Cookie 加
HttpOnly(禁止 JS 读 Cookie)能防 CSRF 吗?(不能,防的是 XSS 偷 Cookie) SameSite(同站策略)干什么? → 也可对照 Cookie 题- 和同源策略什么关系? → 同源策略题
百科对照(可选)
→ XSS 与 CSRF
Hash / History 路由
前端路由 Hash 和 History 有什么区别?实现原理是什么?
对上我的说法
→ 概念 · Hash / History
建议答到的点
- 前端路由三步:拦跳转、改 URL、匹配渲染
- Hash:改
location.hash,听hashchange;#不发给服务器 - History:
pushState改路径,前进后退听popstate;刷新要服务器回退 - 刷新会不会 404、和 SEO 的关系
常追问
pushState会不会触发popstate?(不会,点菜单要自己渲染)- History 刷新为什么会 404?Nginx 怎么配?
- 官网该用哪种?和 SEO 什么关系? → SEO 题
- Vue Router 里对应哪个 API?
百科对照(可选)
→ Hash 与 History
HTTP和HTTPS的区别
HTTP和HTTPS的区别
对上我的说法
→ 概念 · HTTP / HTTPS
→ 底下协议:TCP / UDP · WebSocket
建议答到的点
- HTTP/HTTPS是什么
- WebSocket、TCP、UDP协议
- HTTPS 防窃听、防篡改、防中间人;代价是多一次 TLS 握手
常追问
- TCP 和 UDP 有什么区别?网页为啥不走 UDP? → 下一题
- 三次握手 / 四次挥手干什么? → TCP / UDP
- WebSocket 和 HTTP、TCP 什么关系?怎么建连? → WebSocket
- HTTPS 为什么比 HTTP 慢一点?
百科对照(可选)
→ HTTP 与 HTTPS
→ TCP / UDP
→ WebSocket
TCP 和 UDP 的区别
TCP 和 UDP 有什么区别?三次握手、四次挥手干什么?
对上我的说法
→ 概念 · TCP / UDP
建议答到的点
- TCP / UDP 是什么、核心区别
- 网页为啥走 TCP 不走 UDP
- 三次握手干什么
- 四次挥手干什么
常追问
- HTTPS / WebSocket 底下走哪个? → HTTP / HTTPS · WebSocket
- UDP 常见用在哪?
百科对照(可选)
→ TCP / UDP
强缓存 vs 协商缓存
浏览器缓存机制:强缓存和协商缓存有什么区别?
对上我的说法
→ 概念 · 强缓存 / 协商缓存
建议答到的点
- 强缓存:命中还发不发请求?靠哪些头?
- 协商缓存:怎么问服务端?没变返回什么?
- 两者先后顺序 / 怎么串起来讲
常追问
Cache-Control(缓存控制)和Expires(过期时间)谁优先?ETag(内容指纹)和Last-Modified(上次修改时间)有什么差别?- 304(未修改)和 200(成功,带回新内容)分别意味着什么?
百科对照(可选)
→ 强缓存 vs 协商缓存
Cookie / localStorage / sessionStorage
cookie、localStorage、sessionStorage 有什么区别?
对上我的说法
→ 概念 · 浏览器存储
建议答到的点
- 对比维度:大小、生命周期、是否随请求发送、作用域、设置方式
- Cookie 何时会自动带上请求(domain / path)
- localStorage 与 sessionStorage 差在哪(持久 / 标签会话)
常追问
- 登录态放 Cookie 还是 localStorage?
- 什么是 HttpOnly?前端读得到吗?
- 和 CSRF 有什么关系?(Cookie 会自动带)→ XSS / CSRF 题
百科对照(可选)
→ Cookie / Storage
渲染管线题
浏览器从我们输入 URL 地址到加载完成都做了什么?
对上我的说法
→ 概念 · 浏览器页面渲染管线
建议答到的点
- 拿到地址做了什么操作
- 重排 / 重绘
常追问
- 重排 / 重绘有什么区别? → 下一题
- 如何优化呢?
百科对照(可选)
→ 浏览器 · 页面渲染完整流程
重排重绘题
重排 / 重绘 / 合成有什么区别?如何优化呢?
对上我的说法
→ 概念 · 重排 / 重绘 / 合成
建议答到的点
- 重绘是什么、重排是什么、合成是什么
- 它们有什么区别
- 如何优化
百科对照(可选)
→ 浏览器 · 重排和重绘
同源策略题
什么是同源策略?为什么浏览器要有同源策略?
对上我的说法
→ 概念 · 同源策略
建议答到的点
- 源怎么判(协议 + 域名 + 端口)
- 目的:防恶意页偷别的站数据
- 限制读写跨源数据 / 跨源响应可读性
常追问
- 和「跨域」什么关系? → 跨域题
- Postman / 服务端互相请求有没有跨域?
- 为什么
<script>还能跨域加载?
百科对照(可选)
→ 浏览器 · 跨域与同源
跨域题
什么是跨域?跨域时请求到底发出去了没有?
建议答到的点
- 三者任一不同即跨域
- 常是响应被浏览器拦截,不是没发请求
- 根因落到同源策略
常追问
- 怎么解决?(CORS / 开发代理 / Nginx…)
- 开发代理上线还有用吗?
HTML
H5 新增特性
H5 新增特性有哪些?
对上我的说法
→ 概念 · H5 新增特性
建议答到的点
- 按类说:语义化、表单、多媒体、画布、存储、API,不要只背标签名
- 语义化、
video/audio、canvas/svg、localStorage/sessionStorage - 点出:Cookie 不是 H5 新增
常追问
- 语义化标签具体有哪些、好处? → 下一题 · HTML 语义化
localStorage和 Cookie 差在哪? → Cookie / Storage 题- WebSocket 是 H5 的吗?和 HTTP 什么关系? → HTTP / HTTPS 题
- CSS3 新特性有哪些? → CSS3 题
百科对照(可选)
→ H5 新增特性
HTML 语义化
什么是 HTML 语义化标签?常用有哪些?好处是什么?
对上我的说法
→ 概念 · HTML 语义化
建议答到的点
- 标签本身带含义,不是只靠 class / 样式
- 常用:
header/nav/main/article/section/aside/footer、h1~h6 - 好处:SEO、无障碍、可维护;不等于完全不用
div
常追问
百科对照(可选)
→ HTML 语义化
CSS
CSS3 新特性
CSS3 新增特性有哪些?
对上我的说法
→ 概念 · CSS3 新特性
建议答到的点
- 按块说:圆角阴影、渐变、transform、过渡动画、flex / grid、媒体查询
- 再提
box-sizing、calc、CSS 变量 - 动画优先用
transform/opacity
常追问
transition和animation差在哪? → 百科 · 动画和过渡- flex 常用属性?
flex: 1是什么? → flex / grid 题 - 和重排重绘有什么关系? → 重排重绘题
- H5 新特性有哪些? → H5 题
box-sizing/ 盒模型? → 盒模型题
百科对照(可选)
→ CSS3 新增特性
CSS 优先级
CSS 选择器优先级怎么算?权重相同怎么办?
对上我的说法
→ 概念 · CSS 优先级
建议答到的点
- 四级:行内 > id > class / 属性 / 伪类 > 标签 / 伪元素
- 可记成
(行内, id, class, 标签),从左往右比,不进位 - 权重相同看谁后写;
!important拔高;少用 id 和!important
常追问
!important两边都加比什么?- 通配符
*、继承来的样式权重呢? - Vue 里改子组件样式为什么加
:deep()? → 百科 · :deep
百科对照(可选)
→ CSS 选择器优先级
盒模型
标准盒模型和 IE 怪异盒模型有什么区别?怎么切换?
对上我的说法
→ 概念 · 盒模型
建议答到的点
- 盒子四层:content、padding、border、margin
- 标准
content-box:width只算内容,padding / border 往外撑 - 怪异
border-box:width含内容 + padding + border;用box-sizing切换
常追问
- 项目里为啥全局写
border-box? margin算进width吗?(两种都不算)- 父子上下 margin 合并怎么解? → BFC 题
百科对照(可选)
→ 标准盒模型与怪异盒模型
BFC
什么是 BFC?它解决什么问题?这些问题为什么会出现?
对上我的说法
→ 概念 · BFC
建议答到的点
- BFC 是一块独立的块级布局区域(小房间),里外互不影响
- 先讲清问题从哪来:同一 BFC 里垂直 margin 会合并;float 脱离普通流
- 再讲开 BFC 能干什么:防 margin 合并、清浮动撑高度、两栏不被 float 挡住
- 怎么开:
overflow非 visible、flow-root、float、absolute 等
常追问
- 父子 margin 合并,规范为什么要合并?
- 浮动为什么会让父高度变成 0?
overflow: hidden和display: flow-root怎么选?- 和盒模型什么关系? → 盒模型题
百科对照(可选)
→ 什么是 BFC
position
position 五个值有什么区别?各用在什么场景?
对上我的说法
→ 概念 · position
建议答到的点
- 五个值:
static/relative/absolute/fixed/sticky - 谁脱流、相对谁定位
- 场景:微调、弹层角标、吸顶、表头钉住
常追问
absolute相对谁?找不到定位祖先会怎样?fixed为啥有时不相对视口?(祖先transform等)sticky为什么不吸顶?(没写top,或祖先overflow裁掉了)absolute/fixed和 BFC 有什么关系? → BFC 题
百科对照(可选)
→ position 五个属性
flex / grid / flex:1
flex 和 grid 怎么选?常用属性有哪些?flex: 1 是什么意思?
对上我的说法
→ 概念 · flex / grid
建议答到的点
- flex 管一维(一行或一列);grid 管二维(行和列一起)
- flex:容器主轴 / 对齐 / 换行;子项
flex简写 flex: 1≈1 1 0%,吃剩余空间;兄弟都写就均分- grid:
grid-template-columns、gap、子项跨格
常追问
- 水平垂直居中怎么写?
flex: 1和flex: auto差在哪?- 主轴改成
column之后 justify / align 谁管水平? - 两栏三栏用手写哪页? → 手写与布局
移动端适配
移动端怎么适配?rem、vw、rpx、em、px 有什么区别?
对上我的说法
→ 概念 · 移动端适配
建议答到的点
- 方案:等比缩放(rem / vw)或媒体查询分档;小程序用 rpx
- 单位相对谁:px 固定;% 相对父;em 相对父字号;rem 相对根字号;vw/vh 相对视口
- H5 常用 rem 或 vw;UniApp / 微信常用 rpx
常追问
- rem 的根字号怎么定?(设计稿宽度 / 10,或 flexible)
- 为啥适配用 rem 不用 em?
- 大屏字会不会无限放大?(vw 要设 max)
- 和 flex 布局什么关系? → flex / grid 题
百科对照(可选)
→ 移动端适配
Less / SCSS
Less、SCSS 是什么?和手写 CSS 有什么区别?
怎么答(口述)
Less、SCSS(Sass 的 CSS 语法,Sass 是 CSS 预处理器)在构建期编成 CSS,浏览器不能直接跑。比手写 CSS 多了变量、嵌套、mixin(混合宏)、运算。和 CSS 变量 --var 不同:预处理器变量编译期定死;--var 运行时可改,换肤常用后者。
展开对照
- 百科 → Less / SCSS
- 构建怎么编 → Loader / Plugin
同款说法(可改口播)
→ 概念 · Less / SCSS
JavaScript
什么是 JS / 单线程
什么是 JavaScript?为什么说它是单线程?
对上我的说法
→ 概念 · JS 单线程
建议答到的点
- 三剑客:HTML 结构、CSS 样式、JS 让页面可操作
- 单线程 = 处理这件事时不能同时处理别的 = 同步任务;好处 / 坏处
- 坏处用 EventLoop(事件循环)解:耗时异步出去,做完再排队回来
常追问
百科对照(可选)
→ 什么是 JS / 单线程
事件循环
什么是 EventLoop?宏任务和微任务怎么转?
对上我的说法
→ 概念 · EventLoop
建议答到的点
- JS 单线程会阻塞;EventLoop 是浏览器宿主提供的,用来处理异步
- 同步在调用栈;异步进队列(宏任务 / 微任务);整段 script 是第一个宏任务
- 一轮:取一个宏任务 → 内部同步 → 清空全部微任务 → UI 渲染 → 下一个宏任务
- 举例:
console/Promise.then/setTimeout打印顺序
常追问
- 微任务里又
then一个,还清不清?(本轮一并清) - 和「什么是 JS」那题怎么接? → 上一题
- Node 和浏览器 EventLoop 差在哪? → 百科 · Node EventLoop
百科对照(可选)
→ EventLoop
var / let / const
var、let、const 有什么区别?
对上我的说法
→ 概念 · 变量声明
建议答到的点(主线)
- 先垫 JS 怎么执行:进入这段代码会创建执行上下文——先处理声明,再从第一行一行一行往下跑(EventLoop 管异步排队,这里说的是当前这段同步代码)
- 三种都是声明方式;再说作用域:
var函数级,let/const块级 let是变量、能再赋值;const是常量、不能换绑- 再比
var和let:顶层var会挂到window,let能访问但不挂;var能重复声明,let不能;var声明前访问是undefined,let直接抛错
可展开
- 变量提升:就是执行上下文第 1 步。
var登记并初始化成undefined;let/const也占坑,但不初始化 - 暂时性死区(TDZ):第 2 步一行一行执行时,还没走到
let/const那一行,名字占着坑但不能用,一碰就ReferenceError - const 怎么赋值:声明时必须给值;后面不能换绑;对象 / 数组可以改内部(
obj.n = 1、push);真要锁死用Object.freeze
常追问
百科对照(可选)
→ var / let / const
函数写法
函数有哪几种写法?
对上我的说法
→ 概念 · 函数写法
建议答到的点(主线)
- 函数声明:
function fn() {},有函数提升,写在后面也能先调用 - 函数表达式:变量接收函数,
const fn = function () {},赋上才能调 - 箭头函数(ES6):本质是表达式,没有自己的
this/arguments,不能new new Function:用字符串造函数,极少用- 对象方法 / class 方法:挂在对象或原型上;class 必须
new,底层还是原型
可展开
常追问
- 箭头函数和普通函数差在哪? → 箭头函数
- JS 怎么做面向对象? → 面向对象
- 上一题变量声明 → var / let / const
百科对照(可选)
→ 函数写法
面向对象
JS 怎么做面向对象?为啥要 class?跟原型有什么关系?
对上我的说法
→ 概念 · 面向对象
建议答到的点(主线)
- 先说要解决啥:很多长得像的对象,用手写一份份对象会疯,所以做一套模具,用
new批量出实例 - JS 的模具底层就是原型;
class只是把「函数 + prototype」写好看 - 对照
new:数据this.xxx在实例自己身上;方法挂prototype大家共享 - 子类
extends接着用爸的,super()必须写在this前(先跑爸的 constructor) - 同样叫
bark,狗和猫各写各的,有这个方法就能调
可展开
#才是真私有,_只是约定c instanceof Dog为啥也是 true?(原型链上有Dog.prototype)- 和原型那题怎么接 → 原型
常追问
百科对照(可选)
→ 面向对象
ES6 新特性
ES6 有哪些新特性?解构、模板字符串、数组对象怎么用?
对上我的说法
→ 概念 · ES6
建议答到的点(主线)
按块报,别一上来背 API:
let/const、箭头函数、class(这三块已有专表题)- 解构赋值:数组
const [a, b] = arr;对象const { name } = obj - 模板字符串:反引号 +
${}插值、可换行 - 扩展运算符
...:拷贝、合并、剩余参数 - 数组:
map/filter/reduce最常考;还有find、includes、flat - 字符串:
includes/startsWith/endsWith、trim、padStart - 对象:简写、展开、
Object.keys/values/entries、Object.assign
可展开
常追问
map和forEach差在哪?(map 返回新数组)...是深拷贝吗?(不是,浅拷贝)??和||差在哪?(??只认 null/undefined)
百科对照(可选)
→ ES6
箭头函数 / 普通函数
箭头函数和普通函数有什么区别?
对上我的说法
→ 概念 · 箭头函数
建议答到的点(主线)
- this:普通函数看谁调用谁,能被
call/apply/bind改;箭头函数没有自己的 this,看定义时外层,改不了 - 箭头函数不能
new,也没有自己的prototype - 箭头函数没有
arguments,用剩余参数...args - 适合回调里保住外层 this;对象方法别随便写成箭头
可展开
call/apply/bind怎么改 this:见概念卡里的 JS,箭头函数改不了- 和上一题五种写法怎么接 → 函数写法
常追问
- 对象里
say: () => this.x的 this 是谁? - 为啥 Vue/React 回调里常用箭头函数?
百科对照(可选)
→ 箭头函数 vs 普通函数
JS 数据类型
JS 有哪些数据类型?基本类型和引用类型有什么区别?
对上我的说法
→ 概念 · 数据类型
建议答到的点(主线)
- 两大类:基本类型(原始类型)和引用类型
- 基本类型答六个:
string、number、boolean、null、undefined、symbol(追问可加bigint,算 7 种) - 引用类型主要是对象:普通对象、数组、日期等都是
object;函数本质也是对象,typeof会单独返回'function' - 区别扣「存什么」:基本类型变量里存值,赋值拷值、互不影响、
===比值;引用类型变量里存地址,赋值拷地址、可能共看一份、===比是不是同一个引用
可展开
typeof null:是'object',历史坑,别当成引用类型的判断依据 → 下一题- 怎么判断类型:简单原始值用
typeof;认数组用Array.isArray/instanceof;精细区分用Object.prototype.toString.call - 和 const 怎么接:
const锁的是绑定(指针);基本类型等于锁死值,引用类型不换地址就可以改内部
常追问
null和undefined差在哪? → 百科 · null / undefined- 拷贝对象怎么拷?浅拷贝 / 深拷贝 → 手写 · 深浅拷贝
==/===、隐式转换、instanceof? → 隐式转换与比较- 上一题函数有哪几种写法? → 函数写法
- 再上一题
const对象为啥还能改? → 变量声明
百科对照(可选)
→ 数据类型
隐式转换与比较
什么是隐式转换?== / === 怎么比?怎么判断类型?instanceof 和原型有什么关系?
对上我的说法
→ 概念 · 隐式转换与比较
建议答到的点(主线)
- 隐式转换:你没写
Number()/String(),引擎自己转。常见:==、+、if/&&/||、对象走valueOf/toString - 比相不相等:
==先转再比;===不转,类型和值都要一样。业务默认=== - 比较类型:
typeof看基本类型(null会骗你);要认数组/实例用instanceof或Array.isArray;精细用Object.prototype.toString.call - 比较原型:
instanceof沿左边原型链往上走,看右边的prototype在不在链上
可展开
- 假值:
0、空串、null、undefined、NaN、false转布尔是假;空数组空对象反而是真 - null / undefined:
undefined是还没有;null是主动说空;==时两者相等,===不相等 - typeof null:历史 bug,类型标签被当成对象
- 跨 iframe:
instanceof Array可能不准,认数组用Array.isArray
常追问
[] == ![]为啥是 true?(别背表,说==会隐式转换,业务用===)- instanceof 底层怎么走? → 原型 / instanceof
- 和上一题数据类型怎么接? → 数据类型
百科对照(可选)
→ 隐式转换与比较
原型 / 原型链
什么是原型、原型对象、原型链?
对上我的说法
→ 概念 · 原型链
建议答到的点(主线)
- 声明函数时,身上有
prototype(原型对象),给后面new出来的实例当模板,方法挂上面大家共享 - 对象的
__proto__(原型)指向这份模板:new出来的对象的__proto__等于函数的prototype - 原型链:找属性先看自己有没有,没有就顺着
__proto__往上找,找到就用;找到Object.prototype再往上是null,这条查找链路就是原型链
可展开
- instanceof:沿左边原型链看右边
prototype在不在上面 - new:建空对象 → 挂原型 → 当 this 跑构造 → 返回对象(构造若返回对象则用返回值)
- class:语法糖,底层还是原型;
extends也是在连原型 - 继承:老写法组合 / 寄生组合;现在直接
class Child extends Parent
常追问
- instanceof 沿链怎么走? → 百科 · instanceof
- new 四步 / 手写? → 百科 · new · 手写 new
- 和上一题「比较原型」怎么接? → 隐式转换与比较
百科对照(可选)
→ 原型 / 原型链
闭包 / 内存泄漏 / GC
什么是闭包?和内存泄漏、垃圾回收有什么关系?
对上我的说法
→ 概念 · 闭包 / GC
建议答到的点(主线)
- 闭包:里面的函数还能用外面的变量,哪怕外面的函数已经执行完了(计数器例子)
- 好处是数据私有、保存状态;坏处是被记着的变量回收不了,用完要断引用
- 垃圾回收:JS 自动回收,还有引用就不回收;主流是标记清除
- 内存泄漏:该回收的还被挂着;常见全局、定时器、DOM 引用、事件、闭包捏大对象
- 解决对着清引用;排查用 Chrome Memory 堆快照
可展开
常追问
- 闭包一定泄漏吗?(不是,用完断引用就行)
- 引用计数为啥淘汰?(循环引用计数到不了 0)
事件捕获 / 冒泡
什么是事件捕获和事件冒泡?事件委托是什么?
对上我的说法
→ 概念 · 事件传播
建议答到的点(主线)
- 点一下会在 DOM 树上走三阶段:捕获(外→里)→ 目标 → 冒泡(里→外)
addEventListener第三个参数默认false听冒泡,true听捕获stopPropagation停传播;preventDefault停默认行为,两码事- 委托:利用冒泡把子事件绑到父级,少监听,动态节点也能点到
可展开
e.target和e.currentTarget(点的是谁 / 绑监听的是谁)- Vue 里
@click.stop/.prevent就是这两下
常追问
- 为啥列表不用每个 li 绑一次? → 委托
- 下一题 Vue → Vue 是什么
百科对照(可选)
→ 事件捕获 / 冒泡 / 委托
Vue 基础
Vue 是什么
Vue 是什么?和 jQuery、React 有什么区别?优势在哪?
对上我的说法
→ 概念 · Vue 是什么
建议答到的点(主线)
- Vue 是渐进式前端框架,用来做界面;核心是数据驱动,改数据视图更新
- 和 jQuery:jQuery 命令式自己改 DOM;Vue 声明式,有组件、响应式
- 和 React:都是组件 + 虚拟 DOM;Vue 模板 + 官方全家桶;React JSX + 生态自选
- Vue 优势:渐进式、上手快、官方路由/Vuex、
v-model、国内资料多
可展开
- 双向绑定怎么做的? → 双向数据绑定
- 虚拟 DOM 相对真实 DOM? → 架构 · 虚拟 DOM
- 和 React / Angular 怎么选型?Vue2 vs Vue3? → 架构 · 按场景选型
常追问
百科对照(可选)
→ Vue 是什么
双向数据绑定
Vue2 双向数据绑定怎么实现的?Object.defineProperty 有什么缺点?
对上我的说法
→ 概念 · 双向数据绑定
建议答到的点(主线)
- 双向 = 数据变视图变,视图输入再写回数据
- Vue2 用
Object.defineProperty劫持 getter/setter:读时收集 Watcher,改时通知更新 v-model是绑值 + 听 input,不是另一套原理- 缺点:新增/删除属性侦测不到;数组下标、改 length 不直观;要递归劫持,初始化贵
可展开
- 新增属性怎么办?(
Vue.set/this.$set) - 数组为啥能
push?(重写了变异方法)
常追问
- 上一题 Vue 是什么 → Vue 是什么
- 下一题生命周期 → Vue 生命周期
- 虚拟 DOM 优势(进阶)→ 架构 · 虚拟 DOM
百科对照(可选)
→ Vue2 双向数据绑定
Vue 生命周期
Vue 生命周期有哪些?每个钩子做什么?
对上我的说法
→ 概念 · Vue 生命周期
建议答到的点(主线)
- 按四段说:创建 → 挂载 → 更新 → 销毁
created有 data,能请求,没有真实 DOM;mounted才能碰 DOM、第三方库beforeDestroy清定时器、解绑事件、取消请求
可展开
- keep-alive 不走销毁,走
activated/deactivated→ 百科 · keep-alive - 父子顺序:父 created 先于子;子 mounted 先于父;销毁子先拆
常追问
百科对照(可选)
→ Vue2 生命周期
常用指令
Vue2 常用指令有哪些?v-if 和 v-show 怎么选?computed、watch、methods 有什么区别?
对上我的说法
→ 概念 · 常用指令
建议答到的点(主线)
- 常用指令:
v-bind绑属性、v-on绑事件、v-model双向、v-for循环、v-if/v-show显隐 v-if假就不渲染,切换会销毁创建;v-show一直在 DOM,靠 CSS 显隐;频繁切用 showmethods每次调用都跑,适合点击;computed有缓存、必须有返回值,适合派生展示;watch盯变化做副作用
可展开
v-html注意 XSS;v-for要配稳定key→ 百科 · key- computed 能算出来的,别用 watch 去改另一个值给模板
常追问
百科对照(可选)
→ 常用指令 / if-show / computed
组件传值
Vue2 组件之间怎么传值?分别用在什么场景?
对上我的说法
→ 概念 · 组件传值
建议答到的点(主线)
- 按关系说:父子、兄弟、跨多层、全局
- 父子:父传子
props,子传父$emit;子不要直接改 props - 兄弟:共同父中转或 event bus;跨多层
provide/inject;全局 Vuex - 再补:
$refs调子方法;$attrs/$listeners透传
可展开
- 组件上的
v-model也是 props + emit - bus 为啥大项目慎用?(满天飞,不好追)
常追问
百科对照(可选)
→ 组件传值
路由传值
路由之间怎么传值?query 和 params 有什么区别?有什么坑?
对上我的说法
→ 概念 · 路由传值
建议答到的点(主线)
- 两种:
query挂?id=1;params走路径/user/:id - 取:
this.$route.query/this.$route.params - query 刷新还在;params 必须配进 path,只靠 name 传刷新会丢
- 敏感信息别放 URL;重要数据可进页再请求或自己存
可展开
params一般配name跳;query用path也能带- 刷新丢 Vuex 和这条是两件事 → 百科 · 刷新丢数据
常追问
百科对照(可选)
→ 路由传值
Vuex
Vuex 的五要素是什么?怎么做持久化?
对上我的说法
→ 概念 · Vuex
建议答到的点(主线)
- 五要素:
state存、getter算、mutation同步改、action异步再 commit、module拆 - 改数据走 dispatch → commit,别在 action 里直接改 state
- mutation 必须同步(DevTools 快照)
- 刷新内存空:token 等存
localStorage,启动灌回;业务数据进页再请求;可用vuex-persistedstate
可展开
- 为啥不把整个 store 都持久化?(体积大、易脏、敏感数据)
- mutation / action 细讲 → 百科 · mutation
常追问
百科对照(可选)
→ Vuex 五要素与持久化
Vue3 基础
Vue3 双向绑定
Vue3 双向绑定怎么实现的?和 Vue2 比底层差在哪?
对上我的说法
→ 概念 · Vue3 双向绑定
建议答到的点(主线)
- 还是劫持 + 依赖收集;
v-model仍是绑值 + 事件 - 底层换成
Proxy,代理整个对象,能侦测增删属性,数组下标也好使 - 组合式用
ref/reactive;脚本里ref要.value - 组件
v-model默认modelValue+update:modelValue
可展开
- 指令、
v-if/v-show、路由query/params和 Vue2 同一套,不再单开 watchEffect是 Vue3 多出来的,主线仍是 computed / watch / methods
常追问
百科对照(可选)
→ Vue3 双向绑定
Vue3 生命周期
Vue3 生命周期怎么写?和 Vue2 差在哪?
对上我的说法
→ 概念 · Vue3 生命周期
建议答到的点(主线)
- 选项式四段还在,销毁改名
beforeUnmount/unmounted - 组合式在
setup/<script setup>里写onMounted、onBeforeUnmount setup相当于beforeCreate+created,没有this- 请求不碰 DOM 仍可早发;碰 DOM、图表必须
onMounted;卸载前清定时器
可展开
- keep-alive 仍是
onActivated/onDeactivated
常追问
百科对照(可选)
→ Vue3 生命周期
Vue3 组件传值
Vue3 组件之间怎么传值?和 Vue2 比什么变了?
对上我的说法
→ 概念 · Vue3 组件传值
建议答到的点(主线)
- 关系没变:父子、兄弟、跨多层、全局
- 组合式:
defineProps/defineEmits;父调子要defineExpose - 没有
$on,实例不能当 bus;全局换 Pinia $listeners并进$attrs;组件 v-model 默认modelValue
可展开
- provide 的值要用
ref才响应式
常追问
百科对照(可选)
→ Vue3 组件传值
Pinia
Pinia 怎么用?和 Vuex 比简单在哪?怎么持久化?
对上我的说法
→ 概念 · Pinia
建议答到的点(主线)
- Vue3 官方推荐状态库,对标 Vuex
- 没有 mutation,
action里直接改state;一个 store 就是一个模块 defineStore+ 组件里useXxxStore()- 持久化和 Vuex 一样:刷新内存空,token 存
localStorage或pinia-plugin-persistedstate
可展开
- TS 友好、体积小、和 Composition 一致
常追问
- 为啥去掉 mutation?(少一层,action 里改就行)
- 上一题 Vue3 组件传值 → Vue3 组件传值
- 下一题 UniApp → UniApp 是什么
百科对照(可选)
→ Pinia
UniApp
UniApp 是什么
UniApp 是什么?多端怎么编译?条件编译怎么用?
对上我的说法
→ 概念 · UniApp 是什么
建议答到的点(主线)
- 一套 Vue 语法,编译到 H5、小程序、App
- 公共逻辑复用,端差异用条件编译和平台 API
#ifdef是这个端才编进去,#ifndef不是这个端才保留
可展开
- 微信小程序:
MP-WEIXIN;只 H5:H5
常追问
- 上一题 Pinia → Pinia
- 下一题生命周期 → UniApp 生命周期
UniApp 生命周期
UniApp 生命周期和 Vue 有什么不一样?onLoad、onShow、onReady 怎么用?
对上我的说法
→ 概念 · UniApp 生命周期
建议答到的点(主线)
- 三层:应用
onLaunch/onShow;页面onLoad等;组件仍用 Vue 的mounted - 第一次进页:
onLoad→onShow→onReady onLoad只一次,接路由参数;onShow每次显示都走,适合刷新;onReady首次渲染完才能查节点- 页面没销毁再回来,多半只走
onShow,不再onLoad
可展开
- H5 更像 Vue + 浏览器路由;小程序/App 页面钩子更全
常追问
- 请求放哪?(接参、首次请求
onLoad;每次回页刷新onShow) - 上一题 UniApp 是什么 → UniApp 是什么
- 下一题路由 → UniApp 路由
百科对照(可选)
→ 生命周期差异 · onLoad / onShow
UniApp 路由
UniApp 怎么跳页面、怎么传参?有哪些坑?
对上我的说法
→ 概念 · UniApp 路由
建议答到的点(主线)
navigateTo压栈;redirectTo替换当前;reLaunch清空重开;switchTab切 tab;navigateBack返回- 参数挂 url,
onLoad(options)取;要encodeURIComponent switchTab不能 url 传参,放 store / storage- 参数太长易截断,只传 id;页面栈大约 10 层,别一直 navigateTo
- 回传可用
eventChannel
常追问
- 上一题生命周期 → UniApp 生命周期
- 下一题分包 → UniApp 分包
百科对照(可选)
→ 页面跳转
UniApp 分包
小程序为什么要分包?UniApp 怎么配?
对上我的说法
→ 概念 · UniApp 分包
建议答到的点(主线)
- 主包有体积上限,先下主包才能启动;分包进页再下,启动更快
pages.json里subPackages,root+ 里面的pages- 首页、tabBar 必须在主包
preloadRule可预下载分包;独立分包更彻底隔离
常追问
百科对照(可选)
→ 分包
rpx 与体积
rpx 和 px、vw 有什么区别?UniApp 体积怎么压?
对上我的说法
→ 概念 · rpx 与体积
建议答到的点(主线)
px写死;rpx按屏宽 750 换算,小程序最常用;vw是视口百分比- 体积:分包减主包、图压缩/CDN、组件按需、条件编译砍其它端、构建分析
- 权限:
getSetting→ 调 API 写 fail → 拒绝就openSetting,同时做降级
常追问
架构 · 进阶
技术选型(按场景)
前端怎么做技术选型?官网 / H5 / 中后台 / 小程序 / 微前端分别怎么考虑?
怎么答(口述)
技术选型先看场景:官网、中后台、H5、小程序,约束不同选法就不同。
官网要 SEO(Search Engine Optimization,搜索引擎优化),爬虫吃的是服务器返回的 HTML,常用 Next 或 Nuxt 做 SSR(Server-Side Rendering,服务端渲染)/ SSG(Static Site Generation,静态站点生成),让 HTML 里先有正文;纯客户端 SPA(Single Page Application,单页应用)首包常是空 #app,不适合当官网默认方案。中后台不在乎 SEO,Vue 或 React 加组件库做 CSR(Client-Side Rendering,客户端渲染)就行。微信活动页一般只在微信里打开、不靠外搜,SEO 不是重点;更看适配、包体、微信 JSSDK(JavaScript Software Development Kit,网页 JS 开发工具包)。小程序看 uni 还是原生;多团队巨石再谈微前端。
同形态再补 Vue / React;场景先定,框架后选。
同款说法(可改口播)
→ 概念 · 按场景选型
Vue2 vs Vue3
Vue2 和 Vue3 有哪些核心区别?
怎么答(口述)
Vue2 和 Vue3 指令、v-if / v-show、路由传参这些基础用法差不多,差在取舍。
响应式:Vue2 是 Object.defineProperty,Vue3 换成 Proxy,增删属性和数组更好用。组织代码:选项式到组合式。销毁钩子改名 unmount。状态库 Vuex 换 Pinia。还能提多根、Teleport、TypeScript(类型系统)、tree-shake(摇树优化)。
新项目倾向 3:响应式坑少、编译打包更好、TypeScript 和组合式更友好、官方生态都在 3 上。老项目能跑就不必硬换。
展开对照
- 响应式 → 双向绑定 · Vue3 Proxy
- 生命周期 → Vue2 · Vue3
- 状态库 → Vuex vs Pinia · Vuex · Pinia
- 百科 → 架构 · Vue2 vs Vue3 · Vue3 核心区别
同款说法(可改口播)
→ 概念 · Vue2 vs Vue3
Vuex vs Pinia
Vuex 和 Pinia 有什么区别?为什么 Vue3 用 Pinia?
怎么答(口述)
Vuex 和 Pinia 都是管全局状态的。Vue2 常用 Vuex,Vue3 官方推 Pinia,对标 Vuex、写法更简单。
Vuex 改 state 必须走同步的 mutation,异步放 action 再 commit,模块要嵌进一个大 store。Pinia 没有 mutation,action 里直接改;一个 defineStore 就是一个独立 store,TS 也好写。
持久化两边一样:刷新内存空,登录态存 localStorage 再灌回,列表详情进页再请求。Vue3 用 Pinia 是因为官方推、样板少。状态很少,props / provide 够用也可以先不上。
展开对照
- 用法 → Vuex · Pinia
- 百科 → 架构 · Vuex vs Pinia · Vue2 · Vuex · Vue3 · Pinia
- 上一题 → Vue2 vs Vue3
- 下一题 → 虚拟 DOM
同款说法(可改口播)
→ 概念 · Vuex vs Pinia
虚拟 DOM
虚拟 DOM 是什么?对比直接操作真实 DOM 有什么优势?
怎么答(口述)
虚拟 DOM(Virtual DOM,虚拟文档对象树)用 JS 对象描述真实 DOM(Document Object Model,文档对象模型)。数据一变,先在内存里 diff(差异对比),再 patch(打补丁)到真实 DOM。
比直接改真实 DOM:一改常带重排重绘,贵;虚拟 DOM 在内存里算差异、合并更新,少瞎改。同一套描述还能跨端渲染。不是绝对更快,复杂页面、频繁更新时更划算。
展开对照
- 百科 → 架构 · 虚拟 DOM · Vue2 细节 · diff · key
- 重排重绘 → 重排重绘题
- 下一题 → Vite vs Webpack
同款说法(可改口播)
→ 概念 · 虚拟 DOM
Vite vs Webpack
Webpack 和 Vite 有什么区别?Vite 为什么快?
怎么答(口述)
Webpack 开发常先打包再启动,项目一大就慢。Vite 开发不先全量打包:源码走浏览器原生 ESM(ECMAScript Modules,ECMAScript 模块),按需请求;第三方依赖用 esbuild 预构建成 ESM,冷启动和热更新都快。生产打包 Vite 交给 Rollup。记:开发快靠 ESM + esbuild,产物靠 Rollup。老 Webpack 能跑不必硬换。
展开对照
- 百科 → 架构 · Vite vs Webpack · 工程化细讲
- 追问打包流程 / Loader → 构建 · 追问
- 下一题(实践)→ 性能优化
同款说法(可改口播)
→ 概念 · Vite vs Webpack
工程 · 实践
性能优化
前端项目性能优化怎么答?(加载 / 渲染 / 打包 / 运行)
怎么答(口述)
性能优化分四块。加载:路由懒加载、图片压缩、CDN(Content Delivery Network,内容分发网络)、HTTP 缓存、骨架屏。渲染:少重排重绘、动画走 transform/opacity、虚拟列表。打包:代码拆包、Tree-shaking(树摇,去掉未用导出)、压缩、分析体积。运行:防抖节流、清监听和定时器。先量再优化,用 Lighthouse 或打包分析找瓶颈。
展开对照
- 百科 → 性能四块 · 重排重绘
- 懒加载 → 懒加载 · 虚拟列表 → 虚拟列表
- 上一题(选型)→ Vite vs Webpack
同款说法(可改口播)
→ 概念 · 性能优化
懒加载
路由 / 组件懒加载怎么做?有什么用?
怎么答(口述)
懒加载别把全站 JS 打进首包。路由写 () => import(...),组件用 defineAsyncComponent,用到再下载 chunk(代码分块)。首屏更小、打开更快;小页不必硬拆,关键路由可 prefetch(预加载)。
展开对照
同款说法(可改口播)
→ 概念 · 懒加载
虚拟列表
大列表卡顿怎么优化?虚拟列表原理是什么?
怎么答(口述)
卡是因为 DOM(Document Object Model,文档对象模型)节点太多。虚拟列表只渲染可视区:容器固定高度,按 scrollTop(滚动距离)算起始下标,只建一屏节点,用总高度撑滚动条,滚动时换数据。还可分页、稳定 key、图片懒加载。
展开对照
同款说法(可改口播)
→ 概念 · 虚拟列表
Axios 封装
Axios 二次封装怎么做?请求 / 响应拦截、token、错误处理
怎么答(口述)axios.create 出实例,统一 baseURL 和超时。请求拦截写 token(令牌),可加 loading。响应拦截先看 HTTP 状态,再看业务 code,成功 return data,失败统一提示再 reject。401(未授权)跳登录或走无感刷新。业务页只调封装方法。
展开对照
同款说法(可改口播)
→ 概念 · Axios 封装
token 无感刷新
access token 过期怎么无感刷新?
怎么答(口述)
access token(访问令牌)过期后,响应拦截里用 refresh token(刷新令牌)换新票。同时只刷新一次,其它 401 请求排队,换成功再带新 token 重试。refresh 接口别走「过期就刷新」死循环;refresh 也失效就清登录态。
展开对照
同款说法(可改口播)
→ 概念 · token 无感刷新
构建 · 追问
Webpack 打包流程
Webpack 打包原理 / 构建流程是什么?
怎么答(口述)
Webpack 从入口文件(entry)出发,顺着 import 建依赖图,每个文件过 Loader(加载器)翻译,Plugin(插件)在生命周期里做 HTML 注入、压缩,最后输出 bundle(打包文件)。记:入口 → 依赖图 → 转译 → 加工 → 出包。
展开对照
- 概念 · 从零讲 → Webpack 流程
- 百科 → Webpack 流程
同款说法(可改口播)
→ 概念 · Webpack 流程
Loader / Plugin
Loader 和 Plugin 有什么区别?
怎么答(口述)
Loader(加载器)按文件类型翻译:.vue 用 vue-loader,新 JS 用 babel-loader,样式用 css-loader。Plugin(插件)管整次构建流程,比如注入 HTML、压缩。口诀:Loader 转文件,Plugin 管流程。
展开对照
- 概念 · 从零讲 → Loader / Plugin
- 百科 → Loader / Plugin
- Less/SCSS → 预处理器题
同款说法(可改口播)
→ 概念 · Loader / Plugin
Tree-shaking
什么是 Tree-shaking?原理是什么?
怎么答(口述)
Tree-shaking(树摇)打包时删掉 import 了但没用到 export,减小体积。前提 ESM(ECMAScript Modules,ECMAScript 模块)能静态分析;CJS(CommonJS)的 require 运行时才定,难摇干净。生产还要压缩、配 sideEffects(副作用声明)。
展开对照
- 概念 · 从零讲 → Tree-shaking
- 百科 → Tree-shaking
- 先懂模块化 → 模块化演进
同款说法(可改口播)
→ 概念 · Tree-shaking
HMR
HMR 热更新原理是什么?
怎么答(口述)
HMR(Hot Module Replacement,热模块替换)开发时改代码只换相关模块,不整页刷新,表单状态尽量保留。开发服编译后通过 WebSocket(全双工通信)通知浏览器换模块。Vite 借原生 ESM 更快;Webpack 靠 HMR 运行时。
展开对照
同款说法(可改口播)
→ 概念 · HMR
Babel
Babel 是做什么的?preset-env 干什么?
怎么答(口述)
Babel(JS 语法转译器)把新语法、JSX(JavaScript XML)转成旧浏览器能跑的代码,不是打包器,常配合 Webpack/Vite。preset-env 按 browserslist 目标浏览器按需转换、按需 polyfill(兼容垫片),避免全量转。
展开对照
同款说法(可改口播)
→ 概念 · Babel
模块化演进
模块化怎么发展?ESM 和 CommonJS 差在哪?
怎么答(口述)
早期 IIFE(立即执行函数)自封装 → Node 的 CJS(CommonJS,require)→ 浏览器 AMD(异步模块定义)→ 现在 ESM(import/export)。ESM 编译期能分析依赖,能 Tree-shaking;CJS 运行时加载、难摇。Vue/Vite 项目默认 ESM。
展开对照
- 概念 · 从零讲 → 模块化
- 百科 → 模块化 · JS · ESM/CJS
同款说法(可改口播)
→ 概念 · 模块化
项目 · 实战
飞啾(uni-app + Vue3 / Vite)。自由发挥:题面只给要点,按「现象 → 根因 → 我怎么做」展开。百科细节 → 项目笔记。
口径:uni-app 不是我选型;难点可先讲高德(合规 → SDK → Vite/ESM),再登录回跳、列表假白横跳。
1 分钟项目介绍
用一分钟介绍你最熟的项目
发挥要点(口述)
做过不少偏后台的业务,面试重点讲 飞啾微信小程序。
口播骨架(按顺序说,别一上来堆技术):
- 为什么讲小程序:后台做过很多,代表项目用飞啾小程序说清楚。
- 和小程序 vs App:小程序后做、版本落后 App;两边不是同一套形态。
- 边界:App 很全(下单、用户入驻、商家入驻等);小程序早期只做 下单 + 核销。
- 演进:后来补 俱乐部入驻、志愿者入驻 等,仍比 App 收敛。
- 收尾:技术/我负责的模块,等追问再展开。
展开对照
同款说法(可改口播)
→ 概念 · 项目介绍
难点总览
项目里遇到的最大难点?怎么排查、怎么解决?
发挥要点(口述)
我会挑自己啃过的几块;高德可作第一块,别吹成超难算法。
- 高德接入(展开见专卡):说难不算硬核。开放文档接口先跑通 → 对照微信合规,小程序不允许 → 改官方 SDK → SDK bundle 撞 Vite ESM → 二次改造加 ESM 导出、不动内部;卡久在 import 钻牛角尖,想通改导出才顺。
- 登录回跳:意图记内存,成功
redirectTo,逻辑抽 Composable。 - 列表假白 / 横跳:假白是整页滚高度没收干净;横跳是前人硬纠偏。改成一屏高
scroll-view页内滚。
展开对照
同款说法(可改口播)
→ 概念 · 难点总览
登录回跳
登录后怎么回到用户原来要去的页面?怎么封装的?
发挥要点(口述)
为了解决什么:用户点发布/报名没登录被拉走,成功后要回对页;返回不能再进登录页。本质是意图保持 + 页面栈干净。
怎么跳:还在当前页办事 → navigateTo 登录 → 成功 navigateBack。登录后要去另一页 → 记 pendingUrl → 成功用 redirectTo 换掉登录页。别再用 navigateTo 叠一层,否则返回先撞登录。
怎么封装:页面只管协议和授权手势;Composable 管拿 code、换 token、拉用户信息、广播;业务入口统一 ensureLogin / withLogin。pendingUrl 只放内存,取消就清;跳登录加锁;Tab 取消登录防 onShow 死循环。
展开对照
同款说法(可改口播)
→ 概念 · 登录回跳
高德接入(合规 → SDK → Vite)
高德接入遇到什么问题?和合规、Vite 有什么关系?怎么改的?
发挥要点(口述)
这段说难不算硬核:不是算法题,核心是合规走弯路 + 构建形态冲突,外加一度排查方向偏了。
按时间讲:
- 第一版:选点接高德,照开放平台文档的接口方式做,文档全、联调快,功能能跑。当时只顾接口和流程,没先确认微信小程序允不允许这种接法。
- 合规:补看微信侧规范后发现,小程序端不允许开放文档那种通用接口接法(更偏 Web/通用场景),要走平台认可路径 → 推倒改接 官方 SDK。收获:第三方能力先问平台认不认,再问接口好不好调。
- 构建冲突:SDK bundle 导出(偏传统整包形态);项目 Vite 默认 ESM(ECMAScript Modules)。Vite 按 ESM 解析,SDK 导出对不上,业务里怎么
import都接不稳。 - 改法:对 SDK 二次改造——不动内部(能力/鉴权逻辑不乱改),向上兼容补一种 ESM 认可的导出,让工程能正常
import。改的是「包怎么被工程认出来」,不是改地图本身。 - 反思:方案本身不玄;真正耗时是默认「问题在我怎么引用」,换各种
import写法硬拧。想通「冲突在导出形态」才灵光一现。真机授权、合法域名等可追问再补。
展开对照
- 百科 → 高德接入(含完整口述段)
- 构建 → Vite vs Webpack · 模块化
同款说法(可改口播)
→ 概念 · 高德接入
列表滚动假白
活动列表 iOS 假白、横跳原因是什么?怎么解决的?
发挥要点(口述)
假白原因:列表用整页滚动;筛选后内容变矮,iOS 上整页「可滚高度」有时没收干净,底部还能滑进空洞。
横跳原因:前人锁外层高度或狂 pageScrollTo 纠偏,和手指抢滚动控制权。
怎么解决:外层页面不滚,内层一屏高 scroll-view 滚列表,换「谁在滚」。不是虚拟列表那类问题。
展开对照
同款说法(可改口播)
→ 概念 · 列表滚动
登录态存储与用户信息分发
token 怎么存?用户信息怎么分发到各页?401 怎么办?
发挥要点(口述)
token:本地存储,请求拦截统一带上。
用户信息:登录成功后拉一次,放进全局状态(store);成功或 401 失效时广播,头像、「我的」等页面一起刷新或清空——分发靠订阅/事件,别每页自己拼。
回跳意图:只放内存,不持久化。
401:清 token、Toast 节流、广播失效,再走同一套登录门控(可带 pendingUrl)。
展开对照
同款说法(可改口播)
→ 概念 · 登录态