前言

很多前端面试问到小程序,只背页面生命周期、双向绑定。但企业面试更看重:真机坑、分包加载、权限、图片上传、性能优化、UniApp 跨端差异、和 Web 项目的区别。 小程序环境不是浏览器,是双线程模型,很多 Web 端写好的逻辑直接搬过来会失效。下面全部是项目实战衍生的拓展面试题。

一、底层基础拓展(双线程模型,面试高频加分题)

1. 微信小程序双线程模型是什么?为什么要设计成双线程?UniApp 打包到小程序之后,双线程还存在吗?

答案: 小程序分为逻辑层 (AppService)渲染层 (WebView),两个线程独立运行,通过native层进行通信。

  • 渲染层:负责页面渲染、wxml/wxss,处理视图;
  • 逻辑层:JS 代码执行,处理业务逻辑、接口请求。

设计目的:防止 JS 执行阻塞页面渲染。浏览器是单线程,JS 长时间运算会卡死页面;小程序 JS 跑在独立线程,不会阻塞视图渲染。 但是代价:逻辑层和渲染层通信是异步,频繁通信会有性能损耗。

UniApp 编译到微信小程序平台,最终产物依然是微信小程序,双线程模型保留。UniApp 只是编译工具,不改变小程序底层运行机制。

业务坑点: 不要频繁setData,每次 setData 都会把数据从逻辑层传给渲染层,大量数据传输会造成页面卡顿。

2. setData 的原理,为什么不建议一次性传入超大对象?

答案: setData的作用:把 JS 的数据,异步拷贝到渲染层,驱动视图更新。 不是直接修改视图,是跨线程数据传输。

  • 大数据:一次性传递几 MB 数据,序列化 + 传输开销很大,页面卡顿;
  • 频繁调用:短时间多次 setData,会堆积通信任务。

✅业务最佳实践:

  1. 只传页面渲染需要用到的字段,不要把整个后端返回对象全部 setData;
  2. 合并多次 setData,减少调用次数;
  3. 长列表不要一次性渲染全部数据,分页加载。

UniApp 中this.$setref/reactive底层最终也会转化为小程序 setData。

二、分包、包体积(上线必考点)

3. 小程序分包是什么?为什么要分包?分包加载机制有哪些限制?

答案: 小程序主包默认 2M,整体所有分包合计上限 20M(微信当前规则)。

  • 主包:必须包含app.json、tabbar 页面,项目入口;主包会在小程序打开时直接下载。
  • 分包:把非首页、低频页面拆成独立包,用到的时候才按需下载,减少小程序首次打开加载时间。

限制:

  1. 分包不能独立访问主包资源之外的文件;分包不能引用其他分包静态资源;
  2. 分包页面不能定义 tabbar;
  3. 分包预下载:进入某个页面,提前预加载后续分包,提升跳转体验。

UniApp 项目打包小程序,pages 目录默认主包;subPackages 配置分包。

4. 分包和独立分包的区别?什么时候使用独立分包?

答案: 普通分包:依赖主包,打开分包页面前,必须先下载主包。 独立分包:不依赖主包,可以直接打开独立分包页面,不用下载主包。 适用场景:活动页、分享落地页,用户扫码直接打开活动页面,不需要加载整个小程序主包。 限制:独立分包无法读取 app.js 里定义的全局变量。

三、权限、登录流程(业务高频,几乎所有小程序项目都有)

5. 微信小程序完整登录流程是什么?wx.login什么时候调用?为什么不能后端直接拿前端 code 换取 openid 之后存储,永久使用?

答案:

  1. 小程序调用wx.login()拿到临时 code;
  2. 前端把 code 传给后端;
  3. 后端携带 code + appid + appsecret 请求微信服务器,换取openid(用户唯一标识)+ session_key;
  4. 后端生成自定义登录 token 返回前端,前端存 storage,后续接口携带 token 鉴权。

关键点: code只能使用一次,五分钟有效期。 session_key 会过期,不能永久有效。不能把 openid 放在前端存储用来鉴权,openid 仅仅是用户标识,不能当做登录凭证。

拓展坑:wx.login不要在页面 onLoad 无脑重复调用,会覆盖 session_key,导致解密手机号、头像失败。一般登录失效时再调用。

6. 小程序获取用户手机号有哪些方式?新版小程序为什么无法直接一键获取手机号?

答案: 旧版本:wx.getUserInfo可以直接拿到用户手机号,微信已经废弃。 当前规则:手机号获取必须由用户主动点击按钮触发,绑定 button 组件open-type="getPhoneNumber",拿到加密信息,传给后端用 session_key 解密得到手机号。 不能自动拉起,必须用户手动点击,微信限制是为了保护用户隐私。

UniApp 写法:open-type="getPhoneNumber",监听getphonenumber事件。

四、图片上传、预览、文件处理(后台业务常见)

7. 小程序图片上传,wx.uploadFile 有什么限制?多张上传怎么处理?

答案: wx.uploadFile一次只能上传一张文件,原生 API 不支持多文件同时上传。 限制:单个文件大小上限 10M。 业务方案: 多图上传有两种方案:

  1. 串行上传:一张上传成功,再上传下一张;稳定性高,适合网络差环境;
  2. 并发上传:Promise.all 同时上传多张;速度快,但是并发太多容易接口报错。

坑点:小程序网络请求超时时间默认 60s,大图上传容易超时;需要做 loading、失败重试、进度监听。

8. uni.previewImage 和 wx.previewImage 的坑点?预览网络图片域名需要配置什么?

答案: 小程序预览图片,所有网络图片域名必须在微信公众平台后台配置 downloadFile 合法域名,否则预览失败。 坑:预览时如果图片地址带参数,域名校验也会匹配;本地临时文件路径不需要域名校验。 UniApp 跨端:在 H5 端 previewImage 逻辑不一样,小程序端最终还是调用微信原生 api。

五、UniApp 跨端专项(面试常问:UniApp 开发小程序的坑)

9. UniApp 一套代码多端编译,开发微信小程序时,最常见的平台差异有哪些?

答案:

  1. 样式差异:小程序不支持部分 css 选择器,不支持*通配符;单位推荐 rpx;H5 支持很多 css 属性,小程序不支持;
  2. API 差异:部分 API 只有小程序才有,H5/App 没有,需要条件编译#ifdef MP-WEIXIN
  3. 生命周期差异:页面生命周期大体一致,但是 App、小程序、H5 组件生命周期存在细微差别;
  4. 组件差异:uni 组件底层编译成平台原生组件,部分组件在小程序端会有样式 bug。

条件编译是 UniApp 跨端核心手段,用来隔离不同平台的差异化代码。

10. UniApp 中 rpx 是什么?和 px 的区别?rpx 转 px 规则?

答案: rpx:响应式像素,小程序独有单位。规定屏幕宽度 750rpx。 换算:在任何设备,750rpx = 屏幕完整宽度。 iPhone 宽度 375px,750rpx = 375px,所以 1rpx = 0.5px。 优势:自动适配不同宽度手机,不用媒体查询。

H5 端 UniApp 会自动把 rpx 编译成 px。

六、页面通信、存储、路由

11. 小程序页面之间通信方式有哪些?各自适用场景?

  1. 路由传参:wx.navigateTo url 拼接参数;适合少量简单数据;缺点:长度有限制,复杂对象需要 JSON 序列化,太长会丢失。
  2. globalData 全局变量:App 实例上挂载全局数据;适合简单全局状态;页面销毁数据还在,刷新小程序丢失。
  3. storage 本地存储:持久化,关闭小程序数据还在;适合用户信息、配置;存储上限 10M,只能存字符串,大量数据不推荐。
  4. 事件订阅(EventChannel):页面跳转的事件通道,适合页面之间实时回调通信。

12. wx.storage 有什么限制?和浏览器 localStorage 区别?

答案: 小程序 storage:单个 key 上限 1M,总容量上限 10M;只能存字符串;同步 API wx.setStorageSync,异步wx.setStorage。 区别:

  1. localStorage 是浏览器,小程序 storage 独立;
  2. 小程序 storage 在小程序卸载后仍然保留;
  3. 小程序 storage 受用户清理缓存影响;
  4. 小程序 storage 不要存放大量数据,读取变慢。

业务规范:不要把大量列表数据存入 storage,只存 token、用户基础配置这类少量信息。

七、性能优化 & 上线排查

13. 小程序性能优化手段,从首屏、渲染、网络三个维度说说

首屏优化:

  1. 分包加载,减少主包体积;删除无用 js、静态图片;图片压缩,使用 webp;
  2. 首屏不要一次性请求大量接口,接口合并;懒加载非首屏资源。

渲染优化:

  1. 减少 setData 调用次数,减少传输数据量;
  2. 长列表使用virtual-list虚拟列表,只渲染可视区域节点;
  3. 减少 wxml 节点数量,避免多余嵌套标签。

网络优化:

  1. 域名提前配置,接口 https;
  2. 接口防抖节流;图片 CDN 压缩;
  3. 预加载、分包预下载。

14. 小程序原生组件和自定义组件的区别,原生组件有什么坑?

答案: 原生组件(camera、video、map、canvas)是微信客户端原生渲染,层级高于普通 webview 渲染组件。 坑:原生组件层级最高,普通 view、弹窗浮层盖不住原生组件;不能用 z-index 控制。 解决办法:弹窗弹出时临时隐藏原生组件。

八、简答背诵汇总(面试快速复习)

  1. 小程序双线程:逻辑层、渲染层,异步通信,频繁 setData 会卡顿。
  2. 分包:主包 2M,分包按需下载,降低首屏加载;独立分包不依赖主包。
  3. 登录:wx.login 拿到 code 换 openid;code 一次性,session_key 会过期。
  4. 手机号获取:必须用户手动点击按钮触发,无法自动获取。
  5. UniApp rpx:750rpx 等于屏幕宽度,自动适配移动端。
  6. 原生组件(map/video)层级最高,普通弹窗盖不住。
  7. storage 上限总 10M,适合少量持久化数据,不适合大量列表。
  8. 多图上传:wx.uploadFile 单张上传,串行稳定性好。

结语

小程序和 Web 前端开发最大差别:环境限制多、有包体积限制、域名白名单、隐私权限严格、双线程通信限制。很多 Web 端写起来很简单的功能,放到小程序里都会有各种限制。 掌握上面这些,面试时不再只会背诵生命周期,可以讲业务落地和踩坑经验,拉开和其他候选人差距。

Logo

一站式 AI 云服务平台

更多推荐