小程序面试真题补充
本篇整理自 6.小程序面试真题-37页.pdf,补充生命周期、登录会话、导航、支付和双线程通信等场景题。
小程序面试真题补充
本篇整理自
6.小程序面试真题-37页.pdf,补充生命周期、登录会话、导航、支付和双线程通信等场景题。
一、运行模型:不是缩小版 Web
小程序运行在宿主提供的容器中。PDF 将它与 H5、WebView、JS-SDK 和 WXML 对照:逻辑层执行 JavaScript,渲染层负责 WXML/WXSS,平台 API 通过桥接层提供。开发者不能像在浏览器里一样直接访问完整 DOM/BOM,也不能假设任意 Web API 都存在。
因此回答“小程序和 H5 的区别”时,重点应放在运行容器、渲染模型、API 权限和发布方式,而不只是语法差异。
二、App、Page、Component 生命周期
App管理应用级启动、前后台切换和全局数据。Page管理单个页面的加载、显示、隐藏和卸载。Component管理可复用视图;组件在页面显示/隐藏时可通过pageLifetimes.show/hide感知宿主页面状态。
常见回调及用途:
| 对象 | 关键回调 | 面试中的职责 |
|---|---|---|
App |
onLaunch、onShow、onHide、onError |
初始化、前后台切换、全局错误 |
Page |
onLoad、onShow、onReady、onHide、onUnload |
取参、刷新、首次渲染完成、清理 |
Component |
created、attached、ready、moved、detached、error |
组件实例和节点树的创建、挂载、移动、销毁 |
Component({
pageLifetimes: {
show() {
// 页面重新显示时刷新必要数据
},
hide() {
// 页面隐藏时暂停轮询或动画
}
}
});
冷启动时常见顺序是 App.onLaunch -> App.onShow -> Page.onLoad -> Page.onShow -> Page.onReady;进入下一页会先让当前页 onHide,返回时触发上一页 onShow,被移出栈的页面才执行 onUnload。初始化数据放在合适的生命周期,避免把一次性请求重复放进 show;页面销毁时清理定时器、订阅和 WebSocket。
组件在 created 时还不能调用 setData,应等到初始化并挂载到页面后再更新;组件所在页面的显示/隐藏则使用 pageLifetimes.show/hide。
三、登录、openid 与会话
PDF 展示的登录链路是“客户端拿临时 code,服务端换取身份”:
- 小程序调用
wx.login()获取短期有效的code。 - 将
code发送到自有服务端,由服务端携带appid、appsecret调用平台接口换取openid、session_key(以及业务所需的 unionid)。 - 服务端把
openid与自有用户/会话记录关联,返回业务 token(或随机 session id),客户端后续请求携带该凭证。 session_key只留在服务端,不能下发到前端或写入日志。
业务 session 可以存放在 Redis 等 KV 存储,并设置过期时间;客户端可把自有 token 存在 storage,但不要把 session_key 放到网络请求或日志中。wx.checkSession() 只能判断当前平台会话是否仍有效;失效时重新执行登录链路。业务 token 的过期和刷新策略仍由自有服务端负责,不能把 checkSession 当作完整鉴权。
四、页面导航栈
PDF 对比了常用导航 API,面试时可按“是否入栈、是否保留当前页、是否只能用于 tabBar”回答:
| API | 典型语义 |
|---|---|
wx.navigateTo |
打开非 tabBar 页面并压入导航栈,原页保留在栈中 |
wx.redirectTo |
关闭当前页后打开非 tabBar 页面,原页出栈 |
wx.switchTab |
切换 tabBar 页面并关闭其他非 tabBar 页面 |
wx.reLaunch |
关闭所有页面后打开目标页,重置导航栈 |
wx.navigateBack({ delta }) |
返回栈中前 delta 层,默认返回一层 |
页面之间可视为由 pageModel 组成的栈。getCurrentPages() 可读取当前页面栈,navigateBack 的 delta 决定返回层数;但不应把页面实例长期保存为全局状态。需要跨页面传值时,优先使用路由参数、全局状态或事件通信,并处理页面重复进入。
五、支付的职责边界
wx.requestPayment 需要服务端先创建订单并取得 prepay_id,再生成签名参数。客户端只接收并传入支付参数:
wx.requestPayment({
timeStamp,
nonceStr,
package: 'prepay_id=' + prepayId,
signType,
paySign,
success() {},
fail(error) {},
complete() {}
});
时间戳、随机串、预支付标识和签名都不能由客户端自行拼出;signType 必须与服务端下单时的签名算法一致。支付结果要以服务端异步通知和主动查询为准,不能只相信前端 success 回调。
六、逻辑层、渲染层与 setData
小程序不是把 JavaScript 直接跑在渲染页面里。逻辑层和渲染层通过桥接传递数据,setData 的数据会跨越这条边界。PDF 后半部分连续展示了 setData,对应的性能追问通常包括:
- 为什么频繁调用会卡顿?因为序列化、跨层传输和渲染都有成本。
- 如何缩小开销?只更新变化字段,例如
setData({ 'list[3].checked': true }),合并同一时机的更新。 - 大列表怎么处理?分页/分批加载、减少单项数据、避免把无关对象挂在页面 data 上,并考虑虚拟列表方案。
setData 完成后再依赖回调读取渲染结果;不要把它当作同步赋值,也不要直接操作不存在的 DOM。
七、发布流程与协作
PDF 给出的发布链路是“提交代码 -> 合并主分支 -> 构建/打包 -> 开发者工具上传 -> 平台审核 -> 发布版本”。多人协作时可将构建和上传接入 Jenkins 等 CI,但仍要在失败时通知开发者,在审核通过后再由有权限的角色发布。版本号、项目备注和回滚版本应可追溯,不能只依赖本地构建产物。
八、启动速度与包体
小程序启动分为冷启动和热启动:进程被销毁后重新进入是冷启动,后台存活期间再次进入通常是热启动。冷启动会准备运行环境、下载/校验代码包并初始化首页,优化重点包括:
- 上传时开启代码压缩,删除无用代码和资源,控制主包体积。
- 将低频页面放入分包,结合分包预下载,避免首次点击时才下载大包。
- 压缩图片并减少首屏资源;非首屏数据在
onLoad或首屏后按需请求。 - 使用本地缓存时设置版本和过期策略,避免一次启动读取过大的同步数据。
- 合并必要的
setData,让首屏先渲染骨架,再渐进填充列表。
后台运行时间过长或内存告警可能触发小程序被销毁,不能假设页面状态永久保留;重新进入时应能从持久化状态恢复。
九、平台 API 与工程边界
调用 wx.* API 前要确认基础库版本、权限和平台限制;网络请求、上传、支付等能力通常还受合法域名和 HTTPS 约束。把平台调用封装成服务层,统一处理错误码、重试、登录失效和埋点,页面只关心业务状态。
十、场景题速答
页面返回后数据为什么没刷新?
页面从后台重新显示时不会重新执行首次加载生命周期。把需要刷新的轻量逻辑放在 onShow,并在请求返回后合并更新;同时避免每次显示都无条件发起重复请求。(知识点:App、Page、Component 生命周期)
登录偶发失效怎么排查?
区分平台 code/session_key 失效、业务 token 过期、服务端换取失败和网络错误。客户端遇到统一的鉴权错误时清理旧 token、串行刷新登录态,再重放一次原请求,避免并发请求同时触发多次登录。(知识点:登录、openid 与会话)
小程序和 H5 如何共用业务代码?
抽离纯数据处理、校验和请求协议;视图、路由和平台 API 通过适配层隔离。不要把浏览器 DOM 代码直接搬进小程序逻辑层。(知识点:运行模型与平台边界)