⼀、JavaScript核⼼原理1.computed与watch监听变化的原理核⼼均依赖Vue响应式系统Proxy/Object.defifineProperty。 -computed⾃动收集内部依赖的响应式数据依赖变化⾃动重新计算有缓存。 -watch主动监听指定响应式数据数据变化执⾏回调⽆缓存⽀持异步。2.统⼀捕获Promise错误ASTbabel-loader思路利⽤Babel遍历抽象语法树AST⾃动给所有Promise节点插⼊.catch(全局错误处理函 数)实现⽆侵⼊式统⼀捕获。 步骤1.编写Babel插件2.遍历AST匹配Promise相关CallExpression3.⾃动注⼊catch回 调3.CommonJS底层原理1.每个⽂件是独⽴模块有独⽴作⽤域2.模块被包装为⾃执⾏函数(function(exports,require,module,__fifilename,__dirname){业务代 码})3.通过module.exports导出、require()同步加载4.模块会被缓存多次require仅执⾏⼀次。4.函数柯⾥化原理核⼼将多参数函数转为单参数嵌套函数利⽤闭包缓存已接收的参数最终统⼀执⾏。作⽤参数复⽤、延迟执⾏、动态⽣成适配不同场景的函数。5.for...in与for...of的区别-for...in遍历对象的键名包括原型链上的键可遍历普通对象不适⽤于数组遍历 -for...of遍历可迭代对象数组、Map、Set等的值不遍历原型链⽆法直接遍历普通对象。6.Vue3注意点与优化点优化点1.响应式基于Proxy性能更优天然⽀持新增属性2.CompositionAPI替代OptionsAPI逻辑复⽤性更强3.⽀持Treeshaking打包体积更⼩4.⽀持Fragment多根节点⽆需额外包裹div5.异步组件、Suspense语法优化异步渲染体验6.全局API挂载在app实例上避免全局污染。注意点setup中⽆法直接使⽤this需通过getCurrentInstance获取组件实例。⼆、TypeScript1.as断⾔的使⽤场景及能否强制类型转换使⽤场景1.获取DOM元素时指定类型2.接返回值类型收窄3.联合类型不确定时指定具体类 型。能否强制转换不能as仅告诉TypeScript编译器“信任当前类型”不会做真实的类型转换真实 转换需⼿动编写逻辑。2.type与interface的区别及使⽤场景区别-interface仅能描述对象、类的结构⽀持继承、合并重复定义会⾃动合并-type可描述任意类型基本类型、联合类型、交叉类型、元组等不可重复定义⽀持更灵活的 类型组合。使⽤场景-描述对象、类、组件props→⽤interface-定义⼯具类型、联合/交叉类型、⼯具函数返回值→⽤type。3.TS声明⽂件.d.ts的作⽤1.给⽆类型的JS库提供TypeScript类型提⽰2.让IDE实现代码提⽰、类型校验提升开发效率3.不参与代码编译不会⽣成最终的JS⽂件4.⽤于全局类型定义统⼀管理项⽬中的公共类型4.JavaScript继承的⽅式1.原型链继承通过prototype实现缺点是⼦类会继承⽗类实例的属性易造成污染2.借⽤构造函数继承通过call/apply调⽤⽗类构造函数缺点是⽆法继承⽗类原型上的⽅法3.组合继承结合原型链和构造函数兼顾属性和⽅法的继承缺点是⽗类构造函数会执⾏两次4.寄⽣组合继承最佳⽅案避免⽗类构造函数重复执⾏完美继承属性和⽅法5.ES6 class extends语法糖底层基于寄⽣组合继承简洁易⽤。三、Vue全家桶1.Vue3判断是否为响应式对象导⼊vue提供的⼯具函数按需使⽤-isReactive(obj)判断对象是否是reactive创建的响应式对象-isRef(val)判断值是否是ref创建的响应式值-isProxy(obj)判断对象是否是Proxy包装的reactive/readonly创建的对象-isReadonly(obj)判断对象是否是readonly创建的只读响应式对象。2.组件递归实现树形结构核⼼条件1.组件必须定义name属性模板中需通过name调⽤⾃⾝2.模板中通过v-for遍历⼦节点递归调⽤⾃⾝组件传递⼦节点数据。⽰例核⼼代码defifineOptions({name:TreeItem});//必须定义name TreeItemv-forchildinitem.children:keychild.id:itemchild/3.ref与reactive的实现原理-reactive仅适⽤于对象/数组通过Proxy代理⽬标对象拦截对象的get/set操作⾃动收集依 赖、派发更新⽀持深度响应式-ref适⽤于基本类型number、string等将基本类型包装成RefImpl实例通过实例的value 属性访问/修改值若传⼊对象底层会⾃动⽤reactive代理。4.provide/inject传值变化监听及⼦组件修改祖⽗组件值1.传值变化监听provide传递ref/reactive包裹的值⼦组件inject后可直接监听值的变化响应式 传递2.⼦组件修改祖⽗组件值provide传递⼀个包含“值setter函数”的对象⼦组件调⽤setter函 数即可修改祖⽗组件的值。最佳实践provide(data,{state:ref(0),setState:(val)state.valueval})5.让keep-alive包裹的组件刷新三种常⽤⽅法优先推荐前两种1.动态修改keep-alive的include/exclude属性先移除组件再重新添加触发组件销毁再创建2.给组件绑定动态key修改key值强制组件重新渲染3.在组件的onActivated钩⼦中重新请求数据或执⾏刷新逻辑不销毁组件仅刷新数据。6.v-model的实现原理v-model是语法糖本质是“props事件”的结合1.原⽣表单元素绑定value属性input事件2.⾃定义组件绑定modelValue属性update:modelValue事件。⾃定义组件实现v-model核⼼代码const propsdefifineProps([modelValue]); const emitdefifineEmits([update:modelValue]); 模板中input:valuemodelValueinput$emit(update:modelValue, $event.target.value)/7.Element组件⼆次封装如何继承原组件事件核⼼透传原组件的事件不破坏原组件的API两种⽅式1.Vue3中通过v-bind$attrs⾃动透传所有属性和事件⽆需额外处理2.⼿动转发 注意若⾃定义事件与原组件事件重名组件⾃⾝事件会覆盖原组件事件。四、⼯程化Webpack/Vite1.Vite⽐Webpack快的原因核⼼差异在开发环境⽣产环境两者差异不⼤Vite⽤Rollup打包Webpack⽤⾃⾝打包1.开发环境加载⽅式-Vite不做全量打包采⽤“浏览器原⽣ESM按需加载”只加载当前⻚⾯所需的模块-Webpack必须先打包所有模块构建依赖图再启动服务修改⼀个⽂件需重新打包。2.预构建差异-Vite⽤esbuildGo语⾔编写速度是JS的10-100倍预构建第三⽅依赖-Webpack⽤JS编写的loader预构建速度较慢。3.热更新Vite热更新是模块级别的Webpack需重新编译相关chunk速度更慢2.Webpack与Vite打包优化⽅法1.代码优化代码分割分包、Tree shaking移除未使⽤代码、压缩混淆Terser2.资源优化图⽚压缩、使⽤WebP/AVIF格式、图⽚懒加载、字体优化内联关键字体3.⽹络优化开启Gzip/Brotli压缩、静态资源CDN部署、预加载preload/prefetch4.依赖优化第三⽅依赖单独打包、按需引⼊依赖避免全量引⼊5.其他移除冗余代码、禁⽤sourceMap⽣产环境、优化loader配置。3.Webpack分包原则及hash区别⼀、分包原则1.⼊⼝⽂件每个⼊⼝⽂件对应⼀个chunk2.异步引⼊通过import()异步引⼊的模块会单独⽣成⼀个chunk3.splitChunks配置根据模块⼤⼩、引⽤次数、是否是第三⽅依赖等规则拆分chunk。⼆、hash区别⽣产环境优先⽤contenthash-hash全项⽬共⽤⼀个hash值任意⽂件修改所有chunk的hash都会变化-chunkhash按chunk⽣成hash同⼀chunk内⽂件修改仅该chunk的hash变化-contenthash按⽂件内容⽣成hash只有⽂件内容修改hash才会变化最精准避免⽆效缓 存。4.npm run dev执⾏的流程1.读取项⽬根⽬录下的package.json⽂件找到scripts中的dev命令2.执⾏dev对应的命令如webpack-dev-server、vite3.读取对应的⼯程化配置⽂件webpack.confifig.js/vite.confifig.js4.构建项⽬依赖图编译代码开发环境不做压缩保留源码便于调试5.启动本地开发服务器如localhost:80806.开启热更新HMR监听⽂件变化⽂件修改后⾃动重新编译、刷新⻚⾯7.可选⾃动打开浏览器跳转到本地服务地址。5.把Vue全家桶vue、vue-router、pinia单独打包的配置⼀、Webpack配置module.exports{ optimization:{ splitChunks:{ cacheGroups:{ vendor:{ test:/[\\/]node_modules[\\/](vue|vue-router|pinia)/,//匹配Vue全家桶依赖name:vendor,//打包后的chunk名称 chunks:all,//所有chunk都参与分包 } } } } }⼆、Vite配置export default{ build:{ rollupOptions:{ manualChunks(id){ //匹配Vue全家桶依赖单独打包为vendor chunk if(id.includes(vue)||id.includes(vue-router)||id.includes(pinia)){returnvendor; } } } } }6.多⼊⼝⽂件打包配置⼀、Webpack配置module.exports{ entry:{//配置多个⼊⼝⽂件main:./src/main.js,//主⼊⼝ admin:./src/admin.js//第⼆个⼊⼝如后台管理系统 }, plugins:[ //为每个⼊⼝⽣成对应的HTML⽂件 new HtmlWebpackPlugin({filename:index.html,chunks:[main]}), new HtmlWebpackPlugin({filename:admin.html,chunks:[admin]})] }⼆、Vite配置export default{ build:{ rollupOptions:{ input:{//多⼊⼝对应多个HTML⽂件 main:./index.html,//主⼊⼝HTML admin:./admin.html//第⼆个⼊⼝HTML} } } }7.打包内存溢出的原因及解决⽅法⼀、原因1.项⽬体积过⼤、依赖过多如引⼊⼤量第三⽅库2.未进⾏分包所有代码打包到⼀个chunk中内存占⽤过⾼3.图⽚、视频等资源未做压缩内联到代码中导致打包时内存不⾜4.Node.js默认内存限制较低约1.4GB⽆法满⾜⼤型项⽬打包需求5.loader配置不合理导致打包过程中重复处理资源消耗内存。⼆、解决⽅法1.增加Node.js内存限制最直接 scripts:{build:node--max-old-space-size4096build.js}//设为4GB2.分包处理通过splitChunksWebpack、manualChunksVite拆分chunk3.优化资源压缩图⽚、视频避免内联⼤型资源4.优化依赖移除⽆⽤依赖按需引⼊第三⽅库5.升级Node.js版本⾼版本Node内存管理更优6.关闭不必要的loader或plugin减少内存消耗。五、浏览器与⽹络1.浏览器垃圾回收机制GC的种类及优缺点主流两种现代浏览器如Chrome采⽤“标记清除分代回收”优化1.标记清除Mark-Sweep最常⽤-优点实现简单、通⽤能处理循环引⽤如A引⽤BB引⽤A⽆其他引⽤时可回收-缺点回收后会产⽣内存碎⽚影响后续内存分配效率。2.引⽤计数Reference Counting⽼⽅案⼏乎被淘汰-优点即时回收当对象引⽤数为0时⽴即回收内存利⽤率⾼-缺点⽆法处理循环引⽤会导致内存泄漏如上述A、B循环引⽤引⽤数永远不为0。2.浏览器缓存及Nginx配置解决修改⽂件不⽣效⼀、浏览器缓存分类1.强缓存⽆需请求服务器直接从本地缓存读取状态码200OK(from disk cache/from memorycache)由Cache-Control控制2.协商缓存请求服务器验证缓存是否有效有效则返回304NotModifified⽆效则返回新资源由 ETag/Last-Modifified控制。⼆、Nginx标准缓存配置避免修改⽂件不⽣效//HTML⽂件不缓存关键避免修改后浏览器仍⽤旧缓存 location~\.html${ add_headerCache-Controlno-cache;//每次都请求服务器验证 }//静态资源JS/CSS/图⽚带contenthash永久缓存location~\.(js|css|png|svg|jpg)${ add_header Cache-Control max-age31536000,immutable;//缓存1年 }三、修改⽂件不⽣效原因1.HTML被缓存2.静态资源未加contenthash3.服务器缓存未清理。2.HTTP报⽂的组成HTTP报⽂分为请求报⽂和响应报⽂结构类似⼀、请求报⽂1.请求⾏请求⽅法GET/POST/PUT等、请求URL、HTTP协议版本2.请求头携带请求相关信息如Content-Type、Cookie、Token、User-Agent等3.空⾏分隔请求头和请求体4.请求体POST/PUT等⽅法提交的数据如表单数据、JSON数据。⼆、响应报⽂1.状态⾏HTTP协议版本、状态码如200/304/404/500、状态描述2.响应头携带响应相关信息如Content-Type、Cache-Control、ETag等3.空⾏分隔响应头和响应体4.响应体服务器返回的数据如HTML、JSON、图⽚等。3.Vue项⽬错误监听全局异步覆盖所有错误同步、异步、Vue 组件、Promise1. Vue 组件内错误Vue3app.config.errorHandler (err, instance, info) {// err错误信息instance组件实例info错误位置如生命周期钩子// 错误上报逻辑}2. 全局同步错误window.addEventListener(error, (e) {// e 包含错误信息、错误文件、行号等})3. 全局异步错误Promise 未捕获错误window.addEventListener(unhandledrejection, (e) {e.preventDefault(); // 阻止浏览器默认报错const err e.reason; // 获取 Promise 错误信息})4. 浏览器发送两次请求的情况OPTIONS 预检核心跨域场景下发送“预检请求OPTIONS”“真实请求”两次请求。触发预检请求的条件满足任意一条且跨域1. 请求方法不是简单方法简单方法GET、POST、HEAD2. 请求头包含自定义头如 Token、Content-Type: application/json 等3. Content-Type 不是简单类型简单类型application/x-www-form-urlencoded、multipart/form-data、text/plain。预检请求的作用验证服务器是否允许当前跨域请求通过后才发送真实请求。5. 强缓存返回的状态码强缓存命中时浏览器不发送请求到服务器直接读取本地缓存返回状态码200 OK (from disk cache) // 从磁盘缓存读取持久化缓存200 OK (from memory cache) // 从内存缓存读取临时缓存关闭浏览器丢失6. POST 请求一定不会触发预检吗不一定POST 请求是否触发预检取决于 Content-Type 和请求头1. 不触发预检的 POSTContent-Type 为简单类型application/x-www-form-urlencoded、multipart/form-data、text/plain且无自定义请求头2. 触发预检的 POSTContent-Type 为 application/json、application/xml 等非简单类型或携带自定义请求头如 Token。7. 网络不好弱网、移动端打开网页慢的优化方案重点针对移动端核心减少资源体积、减少请求、优化加载顺序1. 图片优化使用 WebP/AVIF 格式、压缩图片、OSS 裁剪适配移动端尺寸、图片懒加载先加载缩略图2. 资源优化开启 CDN 加速、开启 Gzip/Brotli 压缩、静态资源分离、移除冗余代码3. 代码优化路由懒加载、组件懒加载、Tree shaking、分包加载4. 接口优化合并请求减少请求次数、接口缓存本地缓存 服务器缓存、防抖节流避免重复请求、接口降级弱网时返回简化数据5. 加载体验骨架屏替代空白页、loading 状态、预加载preload 关键资源、延迟加载非关键资源6. 性能优化避免长任务用 WebWorker 处理、减少重绘重排、内联关键 CSS避免 CSS 阻塞渲染7. 移动端专项合理设置 viewport禁止缩放、减少外链字体内联关键字体、避免使用过大的 JS/CSS 文件。六、CSS1. flex: 1 对应的 CSS 属性flex: 1 是简写属性等价于flex-grow: 1; // 项目在剩余空间中占比1 表示占满剩余空间flex-shrink: 1; // 项目空间不足时收缩比例1 表示允许收缩flex-basis: 0%; // 项目的基准尺寸0% 表示以内容尺寸为基准2. Grid 布局实现水平垂直居中最简洁的写法父容器设置.parent {display: grid;place-items: center; // 同时实现水平、垂直居中等价于 align-items: center; justify-items: center;}3. CSS 层叠上下文定义层叠上下文是一个独立的渲染环境内部元素的层叠顺序只在该环境内生效不影响外部元素。创建层叠上下文的常见条件满足任意一条1. position 属性为 relative/absolute/fixed/sticky且 z-index 不为 auto2. display: flex / inline-flex且子元素的 z-index 不为 auto3. opacity 1透明度小于 14. 使用 transform、filter、backdrop-filter 等属性5. will-change 属性设置为 transform、opacity 等。核心规则父级层叠上下文的层级低于其他层叠上下文时即使子元素 z-index 很高也无法覆盖其他层叠上下文的元素。4. 可继承的 CSS 属性常见可继承属性主要是文本、字体相关color、font-family、font-size、font-weight、font-style、line-height、text-align、text-indent、visibility、cursor、list-style列表样式、letter-spacing、word-spacing。不可继承属性主要是布局、盒模型相关width、height、margin、padding、border、position、display、background、float、clear。5. 同域名、子域名下 Cookie 与 localStorage 的共享规则1. 同域名如 a.com- Cookie完全共享同一域名下所有页面、子路径均可访问- localStorage完全共享同源策略同域名、同协议、同端口即可共享。2. 子域名如 a.a.com 和 b.a.com- Cookie默认不共享若设置 domain: .a.com顶级域名前缀加 .则所有子域名可共享- localStorage不共享同源策略限制子域名属于不同的源即使顶级域名相同也无法共享。七、架构与性能优化1. 百万级别访问量网站的架构设计核心思路缓存 异步 分流 扩容分三层设计一、前端层用户直接访问1. CDN 全站加速静态资源、HTML 页面缓存到就近节点2. 静态资源分离JS/CSS/图片/视频部署到 CDN3. 路由懒加载、图片懒加载、资源压缩、代码分包4. 本地缓存localStorage/IndexedDB、接口缓存HTTP 缓存。二、后端层业务处理1. 负载均衡Nginx 反向代理分发请求到多个服务器2. Redis 缓存缓存热点数据、会话信息减少数据库压力3. 分库分表数据库水平/垂直拆分解决单库单表瓶颈4. MQ 消息队列异步削峰处理高并发请求如订单、支付5. 微服务拆分按业务模块拆分服务独立部署、扩容。三、运维层保障稳定1. 集群部署应用服务器、数据库、Redis 集群避免单点故障2. 监控告警实时监控服务器负载、接口报错、访问量3. 容灾备份数据库定时备份、多地域部署避免数据丢失4. 限流熔断防止高并发压垮服务器如接口限流、服务熔断。2. WebWorker 在性能优化上的应用场景核心WebWorker 是独立于主线程的后台线程可处理耗时的纯 JS 逻辑避免阻塞主线程渲染、交互。主要应用场景1. 计算密集型任务大量数据遍历、排序、筛选、去重、加密解密如 AES 加密2. 数据解析复杂 JSON 解析、Excel 导入解析大量数据、CSV 格式转换3. 媒体处理图片处理如裁剪、压缩、音视频解码、Canvas 离屏绘制复杂动画计算4. 其他大数据导出如导出 10 万条数据到 Excel、复杂算法计算如路径规划。注意WebWorker 不能操作 DOM不能访问 window 对象只能通过 postMessage 与主线程通信。3. localStorage 与 IndexedDB 的区别为什么 IndexedDB 更快核心差异同步 vs 异步、存储能力、性能1. localStorage- 同步操作读取/写入会阻塞主线程- 仅支持字符串存储存储容量小约 5MB- 无索引大量数据读写时卡顿性能差- 适用场景简单小配置、少量数据缓存如用户偏好设置。2. IndexedDB- 异步操作不阻塞主线程- 支持任意类型存储对象、二进制数据等存储容量大无固定限制取决于硬盘- 支持索引、事务查询效率高大量数据读写性能优异- 适用场景大量数据存储、离线缓存、复杂数据查询如离线应用、大数据表格。4. 让大模型支持返回折线图、表格、地图等内容核心思路约定数据格式前端解析渲染上下文保持连贯1. 约定格式让大模型按固定 JSON 格式返回数据包含“类型 数据”示例{ type: line, data: { xData: [1月, 2月], yData: [100, 200] } }line 表示折线图table 表示表格map 表示地图对应不同的渲染逻辑2. 前端解析接收大模型返回的数据流如 SSE 流式返回逐步拼接 JSON解析 type 字段3. 渲染展示根据 type 调用对应组件ECharts 渲染折线图/地图自定义组件渲染表格4. 上下文处理每次对话携带 conversationId大模型根据该 ID 存储历史对话上下文确保后续返回的图表数据与前文连贯前端仅负责渲染不存储完整上下文逻辑。5. 前端跨域问题的完整解决方案面试高频覆盖所有场景核心跨域本质是浏览器同源策略限制同域名、同协议、同端口解决方案分前端临时调试、后端正式解决重点掌握3种常用方案1. 后端 CORS 跨域最常用正式环境首选- 核心后端设置响应头允许前端域名访问无需前端修改代码- 关键响应头Access-Control-Allow-Origin允许的前端域名* 表示允许所有、Access-Control-Allow-Methods允许的请求方法、Access-Control-Allow-Headers允许的自定义请求头如 Token- 注意带 Cookie 跨域时Allow-Origin 不能为 *需指定具体域名且需设置 Access-Control-Allow-Credentials: true。2. 前端 Proxy 代理开发环境首选规避跨域限制- 核心开发环境下通过工程化工具Webpack/Vite配置代理将前端请求转发到后端浏览器无跨域限制- Webpack 配置示例devServer: { proxy: { /api: { target: http://localhost:3000, changeOrigin: true, pathRewrite: { ^/api: } } } }- Vite 配置示例server: { proxy: { /api: { target: http://localhost:3000, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } }3. JSONP 跨域兼容旧浏览器仅支持 GET 请求- 核心利用 script 标签不受同源策略限制的特性动态创建 script 标签请求后端接口后端返回回调函数包裹的 JSON 数据- 缺点仅支持 GET 请求无错误处理机制安全性较低现代项目很少使用。补充面试加分其他方案包括 Nginx 反向代理后端部署时使用与 Proxy 原理类似、postMessage跨窗口/iframe 跨域、WebSocket全双工通信无跨域限制。八、组件化与工程化实践共4题1. 组件库二次封装的方法及注意事项一、封装方法1. 外层创建自定义组件内部引入组件库的组件2. 透传原组件的 props、attrs、events避免破坏原 API3. 封装默认配置如默认样式、默认属性、业务逻辑如统一校验、权限控制、防抖节流4. 暴露自定义方法和事件满足业务需求。二、注意事项1. 不破坏原组件的 API保持兼容性后续组件库升级时封装组件无需大幅修改2. 正确透传 v-model如 Element 组件的 v-model需手动转发 update:modelValue 事件3. 事件正确转发避免遗漏原组件的事件Vue3 用 v-bind$attrs 自动透传4. 不过度封装保持组件灵活性避免封装过深导致无法扩展5. 补全 TypeScript 类型提示提升开发体验6. 统一样式与项目整体风格保持一致避免与原组件样式冲突。2. 自定义指令实现图片加载加载前显示默认图加载完成后显示真实图核心思路绑定指令时显示默认图通过 Image 对象加载真实图加载完成后替换 src。Vue3 实现示例// 注册自定义指令v-img-load app.directive(img-load, { mounted(el, binding) { // 1. 加载前显示默认图可配置为全局默认图 el.src https://xxx/default.png; // 默认图地址 el.style.objectFit cover; // 可选防止图片变形 // 2. 新建 Image 对象加载真实图片 const img new Image(); img.src binding.value; // 指令绑定的真实图片地址如 v-img-loadrealImgUrl // 3. 加载完成替换为真实图片 img.onload () { el.src binding.value; }; // 4. 加载失败显示错误图可选 img.onerror () { el.src https://xxx/error.png; }; } }); 使用img v-img-loadrealImgUrl alt图片 /3. 根据配置 JSON 创建动态表单组件核心思路遍历 JSON 配置根据 type 动态渲染对应表单元素绑定 v-model 和校验规则。步骤1. 定义表单配置 JSON示例const formConfig [ { type: input, label: 姓名, key: name, required: true, placeholder: 请输入姓名 }, { type: select, label: 性别, key: gender, options: [{ label: 男, value: male }, { label: 女, value: female }] }, { type: radio, label: 是否已婚, key: married, options: [{ label: 是, value: true }, { label: 否, value: false }] } ];2. 遍历配置动态渲染表单元素Vue3 模板el-form :modelform :rulesrules el-form-item v-foritem in formConfig :keyitem.key :labelitem.label :requireditem.required el-input v-ifitem.type input v-modelform[item.key] :placeholderitem.placeholder / el-select v-else-ifitem.type select v-modelform[item.key] el-option v-foropt in item.options :keyopt.value :labelopt.label :valueopt.value / /el-select el-radio-group v-else-ifitem.type radio v-modelform[item.key] el-radio v-foropt in item.options :keyopt.value :labelopt.value{{ opt.label }}/el-radio /el-radio-group /el-form-item /el-form3. 动态生成校验规则绑定到表单4. 提交时直接获取 form 对象即为表单填写的数据。4. 切换主题的几种方式四种常用方式优先推荐前两种适配面试背诵重点突出核心逻辑无冗余内容1. CSS变量推荐根节点定义全局主题变量--primary-color、--bg-color切换主题时通过JS修改document.documentElement.style的变量值简洁高效、易维护适配所有现代浏览器。2. 样式文件切换推荐提前编写多套主题样式文件theme-light.css、theme-dark.css通过JS动态创建/替换link标签的href属性加载对应主题样式兼容性好切换逻辑简单。3. 类名切换根节点绑定不同主题类.theme-light、.theme-dark样式中通过类名嵌套定义不同主题样式切换时修改根节点类名适合简单主题场景样式耦合度略高。4. CSS预处理器变量less/sass通过预处理器变量定义主题切换时需重新编译样式文件结合webpack插件适合需要兼容旧浏览器、样式复杂度高的项目缺点是无法动态切换需重新打包。面试补充实际开发中优先用前两种CSS变量适合中小型项目样式文件切换适合大型项目多主题场景。补充说明主题切换需兼顾用户体验与开发效率优先选择无刷新切换方案避免切换时出现页面闪烁同时需适配项目技术栈降低维护成本。此外主题切换后需同步保存用户偏好如存入localStorage下次打开页面自动加载对应主题提升用户体验这也是面试中常被追问的实操细节。