前端小程序面试题
说说微信小程序的生命周期函数有哪些?
三类生命周期:
- 应用级:
App()
注册(全局) - 页面级:
Page()
注册(单页面) - 组件级:
Component()
注册(自定义组件)
应用生命周期(app.js)
onLaunch
onShow
onHide
onError
onPageNotFound
onUnhandledRejection
onThemeChange
页面生命周期
onLoad
onShow
onReady
onHide
onUnload
组件生命周期
created
setData
)attached
ready
moved
detached
error
执行顺序
应用启动:
App.onLaunch → App.onShow → Page.onLoad → Page.onShow → Page.onReady
页面跳转:
当前页onHide → 新页onLoad → onShow → onReady
返回上一页:
当前页onUnload → 上一页onShow
微信小程序的登录流程?
- 传统登录:账号密码/短信验证 → 服务端返回Token
- 小程序登录:通过微信身份标识快速建立用户体系,核心元素:code:临时凭证(wx.login()获取)、openid:用户在小程序的唯一ID
关键步骤
- 小程序调用 wx.login() 获取 code
- 后端用 appid + appsecret + code 请求微信接口
- 微信返回 session_key 和 openid
- 后端生成 3rd_session(关联 openid 和 session_key)
- 小程序存储 3rd_session 并后续请求携带
- 后端校验 3rd_session 有效性
登录态校验
- 方案1:服务端校验有效期(需网络请求)
- 方案2:调用 wx.checkSession()(无网络消耗):
微信小程序中路由跳转的方式有哪些?区别?
核心机制
- 页面栈管理:最多10层页面栈
- 每个页面是一个 pageModel
跳转方式对比
wx.navigateTo
wx.redirectTo
wx.switchTab
wx.navigateBack
delta
参数wx.reLaunch
小程序页面间传值方法详解
URL 参数传递(适合简单数据)
- 通过 wx.navigateTo 或 wx.redirectTo 的 url 参数传递
- 在目标页面的 onLoad 生命周期函数中获取
只支持字符串类型
URL长度有限制(不能超过一定长度)
// 页面A跳转并传值wx.navigateTo({ url: \'/pages/pageB/pageB?id=123&name=test\'})// 页面B接收Page({ onLoad: function(options) { console.log(options.id) // 输出: 123 console.log(options.name) // 输出: test }})
全局变量(适合多页面共享数据)
- 在 app.js 中定义全局变量
- 通过 getApp() 方法获取应用实例
不是响应式的,需要手动触发更新
适合存储用户信息等全局数据
// app.jsApp({ globalData: { userInfo: null, token: \'\' }})// 任何页面获取/设置const app = getApp()app.globalData.token = \'abc123\' // 设置console.log(app.globalData.token) // 获取
本地存储(适合需要持久化的数据)
- 使用 wx.setStorageSync/wx.getStorageSync 或异步API
数据持久化,关闭小程序后仍然存在
有容量限制(10MB)
同步操作可能阻塞UI
// 存储数据wx.setStorageSync(\'key\', \'value\')// 获取数据const value = wx.getStorageSync(\'key\')
事件总线(适合组件间通信)
- 使用 getCurrentPages() 获取页面栈
- 通过页面实例直接调用方法
适合页面返回时传值
需要确保页面栈中存在目标页面
// 获取前一个页面实例const pages = getCurrentPages()const prevPage = pages[pages.length - 2]// 调用前一个页面的方法prevPage.setData({ message: \'来自下一页的消息\' })
EventChannel(页面间通信)
- 通过 wx.navigateTo 的 events 配置建立通信
- 使用 this.getOpenerEventChannel() 获取EventChannel实例
支持双向通信
适合需要持续通信的场景
// 页面Awx.navigateTo({ url: \'/pages/pageB/pageB\', events: { acceptData: function(data) { console.log(data) // 接收来自页面B的数据 } }, success: function(res) { res.eventChannel.emit(\'sendData\', {data: \'来自页面A\'}) // 向页面B发送数据 }})// 页面BPage({ onLoad: function(options) { const eventChannel = this.getOpenerEventChannel() eventChannel.on(\'sendData\', (data) => { console.log(data) // 接收来自页面A的数据 }) // 向页面A发送数据 eventChannel.emit(\'acceptData\', {data: \'来自页面B\'}) }})
bindtap 与 catchtap 对比说明
bindtap
catchtap
bindtap:绑定的事件处理函数执行后,事件会继续向父组件冒泡 点击按钮时,会先触发 childTap,然后触发 parentTap
<view bindtap=\"parentTap\"> <button bindtap=\"childTap\">点击我</button></view>
catchtap:绑定的事件处理函数执行后,会阻止事件继续冒泡 点击按钮时,只会触发 childTap,不会触发 parentTap
<view bindtap=\"parentTap\"> <button catchtap=\"childTap\">点击我</button></view>
实际应用场景
- 使用 bindtap 的情况:
需要父子组件都能响应点击事件时
需要利用事件冒泡机制实现某些功能时
- 使用 catchtap 的情况:
阻止事件冒泡,避免父组件意外触发 提高性能,
减少不必要的事件处理
实现点击穿透阻止(如防止遮罩层下的内容被点击)
小程序的兼容问题有哪些
1. iOS 下 z-index 层级问题
- 问题描述:多个绝对定位元素在 iPhone7、iPhoneX 下可能出现层级错乱。
- 解决方案:确保所有绝对定位元素具有同一个共同的父元素。
2. 键盘遮挡输入框(iOS)
- 问题描述:输入框被系统键盘遮挡。
- 解决方案:开启
adjustPosition
,或页面滚动处理。
…
小程序支付流程
在微信小程序中,bindtap 和 catchtap 都是用于处理点击事件的事件绑定方式,但它们的关键区别在于事件冒泡的处理机制。
- 打开电商小程序点击下单
- wx.login获取用户临时登录凭证凑得,发送到后端换取openId
- 下单时小程序需要将购买的商品id,商品数量,以及用户的openId发送给服务器
- 服务器在接收到这些参数后,商城服务器订单数据,同时经过签名算法向微信支付发送请求,获取预付单的信息,同时将获取的数据再次进
- 行相对规则的签名,向小程序端响应必要的参数
- 小程序端在拿到对应的参数后,调用wx.requestPayment()发起 微信支付,唤醒支付工作台进行支付
- 接下来的一系列操作都是用户来操作,支付密码、指纹、等验证确认支付成功后执行鉴权调启支付
- 微信后台进行健全,在微信后台直接返回给前端支付结果,前端收到了返回的数据后对支付结果进行展示。
微信小程序首屏渲染优化手段
控制代码包大学校
分包加载
首屏数据预请求,数据缓存、避免白屏、用户操作及时反馈
- 请求可以在页面onLoad的时候就加载,减少不必要的https请求,可以用egtSotrageSync等方法将树存储在本地
- 可以在前置页面将一些有用的字段带到当前页面,
- 没有数据的模块可以用骨架伞占位
- 不要过于频繁的使用setData,可以考虑将多次setData合并成一次
…
是最近面试的时候问的的一些问题,目前还在面试中,持续更新ing
点个👍哇~