前端面试题总结——小程序篇
一、说说你对微信小程序的理解?优缺点?
1、定义
微信小程序 是一种不需要下载和安装即可使用的应用,用户可以通过微信扫一扫或搜索直接打开使用,实现了“触手可及”的应用体验。微信小程序的核心优势在于其轻量化、跨平台和社交属性,但同时也存在一些限制和挑战。
2、优点
- 无需安装:用户无需下载和安装,直接在微信中搜索即可使用,节省了手机存储空间
- 跨平台兼容:支持IOS,安卓等多个操作系统,开发者可以一次性开发多个平台的应用,降低了开发成本
- 轻量化设计:专注于核心服务,界面简洁,加载速度快,用户体验流畅
- 社交属性:与微信社交功能紧密结合,用户可以通过微信好友、群组分享小程序,增加曝光度和用户粘性
- 丰富的API支持:提供支付、定位、分享等功能,满足多样化需求
- 低成本推广:通过优化SEO和社交媒体传播,可以有效提高小程序的知名度和用户数量
3、缺点
- 功能限制:由于体积和跨平台的限制,某些复杂功能和性能可能不如原生应用
- 用户体验:界面和交互方式相对简单,可能不如原生应用体验好
- 信息泄露风险:与社交功能结合,存在个人信息泄露的风险
- 用户留存率低:即用即走的特性导致用户留存率较低,需要不断通过营销手段吸引新用户
- 依赖平台生态:高度依赖于微信平台,平台政策调整可能影响小程序的发展
- 更新限制:更新需要经过平台审核,可能影响应用的快速迭代
二、说说微信小程序的生命周期函数有哪些?
微信小程序的生命周期主要包含应用级和页面级两类
1、应用级生命周期函数
- onLaunch:当小程序初始化完成时调用,全局只触发一次,适用于初始化应用逻辑、加载必要的资源或设置全局变量等
- onShow:当小程序启动或从后台进入前台时调用,适用于刷新数据或状态、处理用户从其他应用返回的情况等
- onHide:当小程序从前台进入后台时调用。适用于保存临时数据、清理资源等
- onError:当小程序发生脚本错误或API调用失败时调用。适用于记录错误日志、向服务器发送错误报告等
2、页面级生命周期函数
- onLoad:页面加载时触发,每次打开页面都会调用。适用于初始化页面数据、解析页面路径中的参数等
- onReady:页面初始渲染完成时调用,适用于页面渲染后的操作,如初始化插件和组件
- onShow:页面显示/切入前台时触发,适用于刷新数据和状态、处理用户从其他页面返回的情况等
- onHide:页面隐藏/切入后台时触发,适用于保存数据、清理资源等
- onUnload:页面卸载时触发,适用于清理资源、释放内存等
3、组件级生命周期函数
- created:组件加载时触发
- attached:组件显示/切换前台时触发
- ready:组件初次渲染完成时调用
- moved:组件隐藏时触发
- detached:组件卸载时触发
- error:组件方法抛出错误时触发
4、生命周期函数的分类和作用
- 应用级生命周期函数:管理整个小程序的行为
- 页面级生命周期函数:管理单个页面的行为
- 组件级生命周期函数:管理单个组件的行为
三、说说微信小程序的登录流程?
实现小程序用户体系主要设计到 openid 和 code 的概念:
- 调用 wx.login() 方法会生成 code , 将 code 作为参数传递给微信服务器指定接口,就可以获取用户的 openid
- 对呀每个小程序,微信都会将用户的微信 ID 映射出一个小程序 openid ,作为这个用户在这个小程序的唯一标识
流程
- 通过 wx.login() 获取用户的 code 判断用户是否授权读取用户信息,调用 wx.getUserInfo 获取用户数据
- 由于小程序后台授权域名无法授权微信的域名,所以需要自身后端调用微信服务器获取用户信息
- 通过 wx.request() 方法请求业务方服务器,后端把 appid ,appsecret 和 code 一起发送到微信服务器,appid 和 appsecret 都是微信提供的,可以在管理员后台找到
- 微信服务器返回了 openid 及本次登录的会话密钥 session_key
- 后端从数据库中查找 openid ,如果没有查到记录,说明该用户没有注册,如果有记录,则继续往下走
- session_key 是对用户数据进行加密签名的密钥,为了自身应用安全,session_key 不应该在网络上传输
- 然后生成 session 并返回给小程序
- 小程序把 session 存到storage 里面
- 下次请求时,先从 storage 里面读取,然后带给服务端
- 服务端对比 session 对应的记录,然后校验有效期
四、说说微信小程序中路由跳转的方式有哪些?区别?
微信小程序中路由跳转的方式主要有以下几种:
- wx.navigateTo:保留当前页面,跳转到应用内的某个页面,用户可以通过点击返回按钮回到原页面,适用于页面间需要互相跳转,并且需要保留原页面栈的情况
- wx.redirectTo:关闭当前页面,跳转到应用内的某个页面,与wx.navigateTo不同,redirectTo会关闭当前页面,然后跳转到目标页面,用户无法通过点击返回按钮回到原页面。适用于页面间跳转时,不需要保留当前页面的情况
- wx.switchTab:跳转到tabBar页面,并关闭其他所有非tabBar页面,适用于需要快速切换到某个tabBar页面,并关闭其他所有页面的情况。通常用于底部导航栏的Tab切换
- wx.navigateBack:关闭当前页面,返回上一页面或多级页面,适用于需要返回到上一个或多个页面的情况
- wx.reLaunch:关闭所有页面,打开到应用内的某个页面,适用于需要重启小程序并跳转到某个指定页面的情节,如用户登录后跳转到主页
这些路由跳转方式的区别在于:
- 保留当前页面:wx.navigateTo会保留当前页面,用户可以通过返回按钮回到原页面;而wx.redirectTo会关闭当前页面,用户无法返回
- 关闭当前页面:wx.redirectTo和wx.reLaunch都会关闭当前页面,但wx.reLaunch会关闭所有页面,重新打开新的页面栈;而wx.redirectTo只关闭当前页面,跳转到目标页面
- TabBar页面切换:wx.switchTab用于切换到tabBar页面,并关闭其他所有非Tab页面,通常用于底部导航栏的Tab切换
五、说说微信小程序的发布流程?
发布的流程主要分成三个部分:
- 上传代码:在微信开发者工具中点击上传按钮,填写对应的版本号,确认上传
- 提交审核:带上上传后,登录微信公众号的官网,点击【开发管理】,查看应用详情,找到对应的版本号,提交审核
- 发布版本:当审核通过之后,即可点击发布,发布成功后即可使用新版本小程序
六、说说微信小程序的支付流程?
微信小程序的支付流程主要包括以下几个步骤:
- 打开某个小程序,点击下单
- wx.login 获取用户临时登录凭证 code ,发送到后端服务器换取 openId
- 在下单时,小程序需要将购买的商品Id,商品数量,以及用户的openId传送给服务器
- 服务器在接收到商品Id,商品数量,openId后,生成服务器订单数据,同时经过一定的签名算法,向微信支付发送请求,获取预付单信息(prepay_id),同时将获取的数据再次进行相应规则的签名,向小程序端响应必要的信息
- 小程序端在获取对应的参数后,调用wx.requestPayment()发起微信支付,唤醒支付工作台,进行支付
- 接下来的一些操作都是由用户来操作完成的,包括微信支付密码,指纹等验证,确认支付之后执行鉴权调起支付
- 鉴权调起支付:在微信后台进行鉴权,微信后台直接返回给前端支付的结果,前端收到返回数据对支付结果进行展示
- 推送支付结果:微信后台在给前端返回支付的结果后,也会向后台返回一个支付结果,后台通过这个支付结果来更新订单的状态
其中后端响应数据必要的信息则是 wx.requestPayment 方法所需要的参数 ,如下:
wx.requestPayment({ // 时间戳 timeStamp: '', // 随机字符串 nonceStr: '', // 统一下单接口返回的 prepay_id package: '', // 签名类型 signType: '', // 签名 paySign: '', // 调用成功回调 success () {}, // 失败回调 fail () {}, // 接口调用结束回调 complete () {} })
七、说说微信小程序的实现原理?
网页开发,渲染线程和脚本是互斥的,这也是为什么长时间的脚本运行可能会导致页面失去响应的原因,本质上就是我们常说的 js 是单线程的
而在小程序中,选择了 Hybrid 的渲染方式,将视图层和逻辑层分开,双线程同时运行,视图层的界面使用 WebView 进行渲染,逻辑层运行在 JsCore 中
-
渲染层:界面渲染相关的任务全都在 WebView 线程里执行,一个小程序存在多个界面,所以渲染层存在多个 WebView
-
逻辑层:采用 JsCore 线程运行 JS 脚本,在这个环境下执行的都是有关小程序业务逻辑的代码
1、通信
小程序在渲染层,宿主环境会把 wxml 转化为对应的 JS 对象
在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法把数据从逻辑层传递到渲染层,再经过对比前后差异,把差异应用在原来的 Dom 树上,渲染出正确的视图
当视图存在交互的时候,例如用户点击你界面上某个按钮,这类反馈应该通知给开发者的逻辑层,需要将对应的处理状态呈现给用户
对于事件的分发处理,微信进行了特殊的处理,将所有的事件拦截后,丢给逻辑层交给 JavaScript 处理
由于小程序是基于双线程的,也就是任何在视图层和逻辑层之间的数据传递都是线程间的通信,会有一定的延时,因此在小程序中,页面更新成了异步操作
异步会使得各部分的运行时序变得复杂一些,比如在渲染首屏的时候,逻辑层与渲染层会同时开始初始化工作,但是渲染层需要有逻辑层的数据才能把界面渲染出来
如果渲染初始化工作较快完成,就要等逻辑层的指令才能进行下一步工作
因此逻辑层与渲染层需要有一定的机制保证时序正确,在每个小程序页面的生命周期中,存在着若干次页面数据通信
2、运行机制
小程序启动运行两种情况:
- 冷启动(重新开始):用户首次打开或者小程序被微信主动销毁后再次打开的情况,此时小程序需要重新加载启动,即为冷启动
- 热启动:用户已经打开过小程序,然后在一定时间内再次打开该小程序,此时无需重新启动,只需要将后台状态的小程序切换到前台,这个过程就是热启动
八、说说提高微信小程序的应用速度的手段有哪些?
小程序启动时常常会遇到白屏或者加载中等问题
这是因为,小程序首次启动前,微信会在小程序启动前为小程序准备好通用的运行环境,如运行中的线程和一些基础库的初始化
然后才开始进行启动状态,展示一个固定的启动界面,界面内包含小程序的图标、名称和加载提示图标,此时,微信会在背后完成几项工作:
- 下载小程序代码包
- 加载小程序代码包
- 初始化小程序首页
下载到的小程序代码包不是小程序的源代码,而是编译、压缩、打包之后的代码包
所以,我们可以从加载、渲染两个维度进行优化
1、加载过程
提神体验最直接的办法是控制小程序包的大小,常见手段有如下:
- 代码包的体积压缩可以通过勾选开发者工具中“上传代码时,压缩代码”选项
- 及时清理无用的代码和资源文件
- 减少资源包中的图片等资源的数量和大小(理论上除了小icon,其他图片资源从网络下载),图片资源压缩率有限
并且可以采取分包加载的操作,将用户访问率高的页面放在主包里,将访问率低的页面放在子包里,按需加载
当用户点击子包的目录里,还是有一个代码包下载的过程,这会感觉到明显的卡顿,所以子包不建议拆得太大,当然我们可以采用子包预加载技术,并不需要等到用户点击到子包页面后再下载子包
2、渲染过程
关于微信小程序首屏渲染优化的手段如下:
- 请求可以再网页onLoad就加载,不需要等页面ready后再异步请求数据
- 尽量减少不必要的https请求,可使用 getStorageSync() 及 setStorageSync() 方法将数据存储在本地
- 可以在前置页面将一些有用的字段带到当前页,进行首次渲染(列表页的某些数据 --> 详情页),没有数据的模版可以进行骨架屏的占位
在微信小程序中,提高页面的多次渲染效率主要在于正确使用 setData :
- 不要过于频繁调用 setData ,应考虑将多次 setData 合并成一次 setData 调用
- 数据通信的性能与数据量正相关,因而如果有一些数据字段不在界面中展示且数据结构比较复杂或包含长字符串,则不应该使用 setData 来设置这些数据
- 与界面渲染无关的数据最好不要设置在data中,可以考虑设置在 page 对象的其他字段下
3、总结
小程序启动加载性能:
- 控制代码包的大小
- 分包加载
- 首屏体验(预请求,利用缓冲,避免白屏,及时反馈)
小程序渲染性能:
- 避免不当的使用setData
- 使用自定义组件
-