uni-app 面试知识点梳理
- 一、基础认知(必问)
- 1.1 一句话定义
- 1.2 跨端原理(高频)
- 1.3 uni-app 与 Vue 的关系
- 1.4 Vue2 与 Vue3 选型(面试加分点)
- 二、项目结构与配置
- 2.1 标准目录
- 2.2 pages.json(核心配置,必会)
- 2.3 标签映射(易踩坑)
- 三、生命周期(高频重灾区)
- 3.1 三层生命周期
- 3.2 页面 vs 组件生命周期执行顺序(经典题)
- 3.3 onLoad 与 onShow 区别(必背)
- 四、路由与跳转
- 4.1 五种跳转 API
- 4.2 传参与接收
- 4.3 路由拦截
- 五、网络请求与封装(实战必考)
- 5.1 原生请求
- 5.2 面试级封装要点
- 5.3 文件上传/下载
- 六、状态管理(Vuex / Pinia)
- 6.1 何时需要
- 6.2 Vuex 经典结构
- 6.3 Pinia(Vue3 推荐)
- 6.4 跨页传值替代方案
- 七、条件编译(uni-app 特色,必考)
- 7.1 语法
- 7.2 各位置写法
- 7.3 常用平台标识
- 八、小程序专项(结合实际项目重点)
- 8.1 登录流程(微信小程序必考)
- 8.2 分包加载(性能关键)
- 8.3 rpx 单位
- 8.4 微信支付
- 九、组件通信(Vue 通用 + uni 特有)
- 9.1 通信方式对比
- 9.2 组件生命周期在 uni 中的注意点
- 十、性能优化(高频)
- 十一、易踩坑清单(实战血泪)
- 十二、uni-app X 与新趋势(加分)
- 十三、高频面试题 30 连击(自测)
- 附:答题模板(STAR 简化版)
定位:求职技术岗(uni-app / 小程序前端)面试速通。
范围:以微信小程序为主战场,兼顾 H5 / App。Vue2 + Vue3 双栈覆盖。
用法:每个模块先看"核心结论",再看"面试题",最后对照"易踩坑"。
一、基础认知(必问)
1.1 一句话定义
uni-app 是DCloud 出品的、基于 Vue 语法的跨端应用框架,一套代码可编译到微信/支付宝/百度/抖音小程序、H5、App(iOS/Android)、快应用等。
1.2 跨端原理(高频)
| 层 | 作用 | 说明 |
|---|---|---|
| 编译器(cli/ide) | 把 Vue SFC 编译成各平台目标代码 | 小程序:.vue→wxml/wxss/js/json;H5:标准 Vue;App:weex/uts |
| 运行时(runtime) | 抹平各平台 API 差异 | uni.xxx调用在底层映射到wx.xxx/navigator/plus |
| 条件编译 | 差异化代码 | #ifdef MP-WEIXIN ... #endif |
关键结论:uni-app = Vue 语法 + 平台编译器 + 统一运行时。它不是"套壳 webview",小程序端是原生组件渲染。
1.3 uni-app 与 Vue 的关系
- 模板、数据绑定、组件、生命周期沿用了 Vue。
- 小程序平台下没有 DOM/BOM,
document、window、localStorage在小程序端不存在 → 必须用uni.xxx替代。 - Vue3 版本使用 Vite 编译,性能与 Tree-shaking 更优;Vue2 版本逐步进入维护态。
1.4 Vue2 与 Vue3 选型(面试加分点)
| 维度 | Vue2(Options) | Vue3(Composition + Vite) |
|---|---|---|
| 编译器 | vue-cli / HbuilderX | Vite(更快) |
| 响应式 | Object.defineProperty | Proxy |
| 写法 | data(){return{}}/methods | setup()/<script setup> |
| 状态管理 | Vuex | Pinia(官方推荐) |
| 兼容性 | 老项目多 | 新项目首选 |
二、项目结构与配置
2.1 标准目录
├─ pages/ # 页面(每个页一个文件夹) │ ├─ index/index.vue ├─ components/ # 自定义组件 ├─ static/ # 静态资源(图片等,不被编译) ├─ store/ # Vuex/Pinia ├─ utils/ # 工具(request 封装等) ├─ App.vue # 应用入口(应用生命周期) ├─ main.js # 入口脚本 ├─ pages.json # ★ 路由 + 全局样式 + 分包配置 ├─ manifest.json # 应用配置(appid、名称、图标) └─ uni.scss # 全局样式变量2.2 pages.json(核心配置,必会)
{"pages":[{"path":"pages/index/index","style":{"navigationBarTitleText":"首页"}}],"globalStyle":{"navigationBarBackgroundColor":"#007AFF"},"tabBar":{"list":[{"pagePath":"pages/index/index","text":"首页","iconPath":"..."}]},"subPackages":[{"root":"packageA","pages":[{"path":"list/list"}]}],"preloadRule":{"pages/index/index":{"network":"all","packages":["packageA"]}}}面试题:pages数组第一项是什么?→ 应用启动页(首页)。
2.3 标签映射(易踩坑)
| HTML | uni-app |
|---|---|
<div> | <view> |
<span><a> | <text> |
<img> | <image> |
<input> | <input>/<textarea> |
<ul><li> | 无,用<view>模拟 |
注意:
<text>内只能嵌套文本/文本组件,放<view>不生效。
三、生命周期(高频重灾区)
3.1 三层生命周期
| 层级 | 钩子 | 触发时机 |
|---|---|---|
| 应用级(App.vue) | onLaunch | 应用初始化(全局一次) |
| 应用级 | onShow/onHide | 应用前台/后台 |
| 页面级 | onLoad(options) | 页面加载(传参在这里接收) |
| 页面级 | onShow/onReady/onHide/onUnload | 显示/渲染完成/隐藏/卸载 |
| 组件级(Vue2) | created/mounted等 | 同 Vue |
| 组件级(Vue3) | onMounted等(需 import) | 组合式 |
3.2 页面 vs 组件生命周期执行顺序(经典题)
页面 onLoad → 组件 created → 组件 mounted → 页面 onReady- 页面
onLoad早于组件mounted。 - 页面切走:
onHide;再回来:onShow(组件不重新创建,故created不重复)。
3.3 onLoad 与 onShow 区别(必背)
onLoad:页面创建时执行一次,适合初始化、options取参。onShow:每次显示都执行,适合刷新数据(如从详情页返回列表需刷新)。
四、路由与跳转
4.1 五种跳转 API
| API | 表现 | 是否可返回 | 栈上限 |
|---|---|---|---|
navigateTo | 打开新页 | 是 | 10 层 |
redirectTo | 替换当前页 | 否 | — |
switchTab | 跳 tabBar 页 | 否 | — |
reLaunch | 关闭所有重开 | 否 | — |
navigateBack | 返回 | — | — |
易踩坑:
switchTab不能传参(URL 参数会被忽略),跨 tab 传值要用全局状态/本地缓存。navigateTo超过 10 层会失败,需redirectTo或reLaunch兜底。
4.2 传参与接收
// A 页uni.navigateTo({url:'/pages/detail/detail?id=123&name=test'})// B 页 onLoadonLoad(options){console.log(options.id,options.name)// '123' 'test'(均为字符串)}接收值永远是字符串,数字需
Number()转换。
4.3 路由拦截
- 全局:在
App.vue的onShow中根据uni.getLaunchOptionsSync()/ 页面栈做权限判断。 - 推荐用
uni.addInterceptor('navigateTo', {...})做统一登录校验(实战常用)。
五、网络请求与封装(实战必考)
5.1 原生请求
uni.request({url:'https://api.example.com/list',method:'GET',data:{page:1},header:{'Authorization':token},success:(res)=>{},fail:(err)=>{}})5.2 面试级封装要点
- Promise 化:用
return new Promise包裹,支持async/await。 - 拦截器:请求前注入 token,响应后统一处理 401/状态码。
- 错误统一处理:网络错误、业务错误码分层。
- baseURL 环境切换:dev / prod 通过条件编译或 env 区分。
// utils/request.js 简化版constBASE_URL='https://api.example.com'exportfunctionrequest(options){returnnewPromise((resolve,reject)=>{uni.request({url:BASE_URL+options.url,method:options.method||'GET',data:options.data,header:{'Authorization':uni.getStorageSync('token')||''},success:(res)=>{if(res.statusCode===200&&res.data.code===0)resolve(res.data)elseif(res.data.code===401){uni.navigateTo({url:'/pages/login/login'});reject(res.data)}elsereject(res.data)},fail:reject})})}5.3 文件上传/下载
- 上传:
uni.uploadFile({ url, filePath, name:'file', formData }) - 下载:
uni.downloadFile→ 拿到临时路径 →uni.saveFile - 小程序端不能直接操作本地文件系统路径,只能拿到临时路径。
六、状态管理(Vuex / Pinia)
6.1 何时需要
- 跨页面共享(用户信息、登录态、购物车)。
- 全局配置(主题、地区)。
6.2 Vuex 经典结构
// store/index.jsimportVuefrom'vue'importVuexfrom'vuex'Vue.use(Vuex)exportdefaultnewVuex.Store({state:{token:''},mutations:{setToken(s,v){s.token=v}},actions:{login({commit},payload){/* 异步 */commit('setToken',payload)}},getters:{isLogin:s=>!!s.token}})6.3 Pinia(Vue3 推荐)
- 无
mutations,state/actions/getters更直接。 - 天然支持 Composition API,
storeToRefs解构保持响应性。
6.4 跨页传值替代方案
| 场景 | 方案 |
|---|---|
| 兄弟/跨多级页 | Vuex/Pinia |
| 简单临时 | uni.setStorageSync |
| 页面栈直取 | getCurrentPages()取上一页setData |
七、条件编译(uni-app 特色,必考)
7.1 语法
// #ifdef MP-WEIXINconsole.log('只在微信小程序编译')// #endif// #ifndef H5console.log('除了 H5 都编译')// #endif// 多平台// #ifdef MP-WEIXIN || MP-ALIPAY7.2 各位置写法
| 位置 | 写法 |
|---|---|
| 模板 | <!-- #ifdef MP-WEIXIN --> |
| 样式 | /* #ifdef MP-WEIXIN */ |
| 脚本 | // #ifdef MP-WEIXIN |
7.3 常用平台标识
MP-WEIXINMP-ALIPAYMP-BAIDUMP-TOUTIAOH5APP-PLUSAPPMP(所有小程序)。
八、小程序专项(结合实际项目重点)
8.1 登录流程(微信小程序必考)
1. 前端 uni.login() → 拿到 code 2. 把 code 发给后端 3. 后端用 code + appsecret 调微信接口换 openid/session_key 4. 后端生成自定义 token 返回前端 5. 前端存 token,后续请求携带注意:code 只能用小程序的
wx.login/uni.login换,不能前端直接拿 openid(安全)。
8.2 分包加载(性能关键)
- 主包过大(微信限制2MB主包)会导致无法预览/上传 → 必须分包。
- 分包通过
subPackages配置,独立打包,使用时按需下载。 - 分包预下载
preloadRule优化首跳体验。
8.3 rpx 单位
750rpx = 屏幕宽度,自适应各机型。- 设计稿通常按 750px 出图,1:1 写 rpx。
- 注意:rpx 有个别机型 rounding 误差,关键尺寸可用 px 兜底。
8.4 微信支付
- 前端:
uni.requestPayment({ provider:'wxpay', timeStamp, nonceStr, package, signType, paySign }) - 参数由后端统一下单生成,前端只负责调起。
九、组件通信(Vue 通用 + uni 特有)
9.1 通信方式对比
| 方式 | 适用 | 说明 |
|---|---|---|
props/$emit | 父子 | 标准 |
provide/inject | 跨层 | Vue 原生 |
uni.$on/uni.$emit | 任意组件 | uni 事件总线,需uni.$off销毁防内存泄漏 |
| Vuex/Pinia | 全局 | 状态 |
ref | 父调子方法 | this.$refs.child.fn() |
9.2 组件生命周期在 uni 中的注意点
- 小程序组件无
onShow,只有 Vue 的created/mounted等。 - 需监听页面显示时,用
uni.$on('pageShow')在页面onShow中触发。
十、性能优化(高频)
- 分包:控制主包 < 2MB。
- 图片:用 CDN + 压缩,避免本地大图;
lazy-load懒加载。 - 长列表:数据量大用
uni.createIntersectionObserver或虚拟列表,避免一次性渲染。 - v-for 必须 key:用稳定 id,不用 index(小程序重排 bug)。
- 减少 setData 频率/体积:小程序 setData 有性能成本,合并数据、避免传大对象。
- onLoad 初始化 / onShow 轻量刷新:别在
onShow做重活。 - 组件按需引入:非全局组件局部注册。
十一、易踩坑清单(实战血泪)
| 坑 | 现象 | 解决 |
|---|---|---|
| 小程序无 window/document | 报错 undefined | 用 uni API 替代 |
| switchTab 传参无效 | 收不到 | 用 storage/store |
| 页面栈超 10 层 | navigateTo 失败 | redirectTo/reLaunch |
| rpx 误差 | 个别机型错位 | 关键尺寸 px |
| 事件总线未 off | 重复触发 | 页面 onUnload 中$off |
| 本地图片过大 | 主包超限 | 转 CDN / 分包 |
| H5 端跨域 | 请求失败 | 配 proxy 或后端 CORS |
| 真机与模拟器差异 | 样式/API 不一致 | 必须真机调试 |
| v-if 与 v-for 同元素 | 警告/逻辑错 | 拆开或用 computed 过滤 |
| 自定义组件样式隔离 | 外部样式不生效 | options:{styleIsolation:'shared'}或::v-deep |
十二、uni-app X 与新趋势(加分)
- uni-app x:用
uts(TypeScript 风格)直接编译为原生(Kotlin/Swift),性能接近原生,但生态尚在完善。 - Vue3 + Vite已成新项目默认。
- uniCloud:DCloud 的 serverless,前后端一体。
- 面试时如能对比"传统编译型 vs uni-app x 原生型"体现技术视野。
十三、高频面试题 30 连击(自测)
- uni-app 跨端原理是什么?
- Vue2 和 Vue3 在 uni-app 中的区别?
- 页面生命周期与组件生命周期执行顺序?
- onLoad 和 onShow 的区别与适用场景?
- 小程序为什么没有 DOM?如何替代?
- 五种路由 API 及使用区别?
- switchTab 为什么不能传参?怎么解决?
- 页面栈上限是多少?超限怎么办?
- 如何封装 uni.request?
- 401 怎么统一处理?
- 微信小程序登录流程?
- code 能在前端直接换 openid 吗?为什么?
- 什么是分包?为什么要分包?主包限制?
- 分包预下载有什么用?
- rpx 是什么?设计稿怎么对应?
- 条件编译语法?常用平台标识?
- 如何在 H5 和小程序写不同代码?
- Vuex 和 Pinia 区别?uni 推荐哪个?
- 跨页面传值有哪些方式?
- uni.$on 需要注意什么?
- 父子组件通信方式?
- provide/inject 适用场景?
- 小程序支付流程?谁生成签名?
- 如何做路由拦截/登录校验?
- 长列表如何优化?
- setData 为什么有性能成本?如何优化?
- v-for 为什么必须 key?能用 index 吗?
- 真机调试为什么必要?
- 事件总线内存泄漏怎么避免?
- uni-app x 相比传统方案优势?
附:答题模板(STAR 简化版)
被问原理类:先一句话结论 → 再讲分层/流程 → 举项目中的例子。
被问优化类:先说现象/指标 → 再给手段(分包/懒加载/合并 setData)→ 讲你项目里做到了哪一步。