小程序和 React Native 面试题答案
一、小程序经典面试题
1. 小程序的双线程模型是什么?为什么这么设计?
是什么: 小程序的渲染层(WebView)和逻辑层(JsCore)是分开的,分别在两个线程中运行。
为什么(设计初衷):
-
安全性:防止开发者操作 DOM/XHR 直接绕过小程序框架的管控,逻辑层无法直接操作视图,必须通过 setData 通知渲染层更新,方便对数据进行安全校验。
-
性能与体验:逻辑层和渲染层独立运行,即使 JS 逻辑执行繁忙(如计算),也不会阻塞页面的渲染和用户交互,保证了页面的流畅性。同时,多个页面可以共享同一个逻辑线程,减少了资源开销。
2. 请详细说明 setData 的工作原理和优化技巧
工作原理: setData 是连接逻辑层与渲染层的桥梁。调用后,数据会以 JSON.stringify() 后的字符串形式从逻辑层传输到渲染层(Native 做中转),渲染层再通过 JSON.parse() 和 evaluateJavascript() 来更新视图。这是一个异步且开销较大的过程。
优化技巧(必考):
- 减少数据量:只 set 发生变化的数据,避免传递超大对象或长数组。
- 降低调用频率:合并多次 setData 调用,避免在循环中调用。
- 使用路径更新:对于对象或数组的局部更新,使用路径语法。
// 坏
this.setData({ list: newList })
// 好
this.setData({ 'list[0].title': 'New Title' })
- 避开与渲染无关的数据:与渲染无关的数据不要放在 data 中,可直接挂在 this 上。
3. 小程序的生命周期函数有哪些?应用和页面有什么区别?
应用生命周期: onLaunch, onShow, onHide, onError (全局性的)
页面生命周期: onLoad, onShow, onReady, onHide, onUnload, onPullDownRefresh, onReachBottom, onShareAppMessage 等 (页面级的)
区别: App 的生命周期管理整个小程序程序的行为,而 Page 的生命周期只管理单个页面的行为。
4. 小程序的登录流程是怎样的?(OAuth)
这是一个非常经典的流程,务必背熟。
- 前端调用 wx.login() 获取临时 code
- 将 code 发送给开发者服务器
- 开发者服务器拿着 code、自己的 appid 和 appsecret 去微信接口服务端换取用户的 openid 和 session_key
- 服务器根据 openid 生成一个自定义的登录态(例如一个 Token),返回给前端
- 前端存储这个 Token(如存在 Storage),后续请求都带上它,服务器验证 Token 即可识别用户身份
5. 如何实现小程序的自定义组件和通信?
创建: 在 json 文件中声明 { "component": true }
通信:
- 父 -> 子:Properties
- 子 -> 父:triggerEvent 触发自定义事件
- 兄弟/跨组件:使用全局的 getApp() 或小程序自带的 EventChannel (getCurrentPages() 获取页面实例,再调用其方法)
6. 小程序的发布流程和权限管理?
流程: 开发预览 -> 上传代码 -> 提交审核 -> 发布上线
权限管理: 主要通过 app.json 的 permission 字段和某些 API 的调用权限(如用户信息需通过<button open-type="getUserInfo">获取)
二、React Native 经典面试题
1. RN 的原理是什么?如何实现 JavaScript 与 Native 的通信?
核心原理: RN 的 UI 是通过 Native 组件(如 View, Text)渲染的,JS 端负责业务逻辑。它们运行在不同的线程(JS 线程和 UI 主线程)。
通信机制(Bridge):
-
异步、序列化、批处理:JS 和 Native 之间的通信是异步的,所有调用信息(模块名、方法名、参数)都会被序列化为 JSON 消息,通过 Bridge 进行传递,并会被批量处理以提高性能。
-
三个线程:
- JS 线程:执行 JavaScript 代码
- Native/UI 线程:负责原生 UI 的渲染和用户交互
- Shadow 线程:根据 JS 线程传来的布局信息,计算具体的 UI 布局(Yoga 引擎),再通知 UI 线程渲染
2. 列举常见的性能优化手段
-
减少 re-render:使用 React.memo, useMemo, useCallback 避免不必要的渲染
-
减少 Bridge 负载:避免频繁地在 JS 和 Native 之间传递大量数据(如巨大的列表),优化数据结构
-
图片优化:使用合适尺寸的图片,考虑使用 @shopify/react-native-skia 进行图片缓存和优化
-
列表优化:使用 FlatList 或 FlashList(来自 Shopify),并正确实现 getItemLayout, keyExtractor,减少内存占用
-
Hermes 引擎:启用 Hermes 引擎可以显著提升 JS 代码的启动速度和运行性能
3. 什么是 Native Module 和 Native Component?如何在 RN 中调用原生功能?
Native Module: 允许 JS 代码调用原生平台(iOS/Android)提供的 API(如获取设备信息、调用系统相册)
Native Component: 允许开发者自定义一个原生的 UI 组件,并在 JSX 中使用它(如一个特殊的视频播放器)
如何调用: 需要分别在 iOS(Objective-C/Swift)和 Android(Java/Kotlin)端编写原生代码,并通过 RCT_EXPORT_MODULE 和 RCT_EXPORT_METHOD 等宏暴露给 JS 层调用
4. 如何处理 RN 中的样式差异和平台适配?
Platform 模块:
import { Platform } from 'react-native'
const styles = StyleSheet.create({
box: {
marginTop: Platform.OS === 'ios' ? 20 : 10, // 平台区分
...Platform.select({
// 平台选择
ios: { backgroundColor: 'red' },
android: { backgroundColor: 'blue' },
}),
},
})
特定文件后缀: Component.ios.js 和 Component.android.js,RN 会自动识别并加载对应平台的组件
5. RN 如何实现热更新?原理是什么?
实现: 使用微软的 CodePush 或第三方热更新服务
原理: 将编译好的 JS Bundle 文件(包含业务逻辑代码)上传到云服务器。App 启动时或特定时机下,向服务器查询是否有新版本 Bundle,然后下载并替换本地的旧 Bundle 文件,从而达到更新应用逻辑的目的,无需通过应用商店审核
6. RN 0.60+ 版本有哪些重大更新?
-
自动链接 (Autolinking): 极大简化了原生依赖的链接过程,大部分情况只需 yarn add 即可,无需手动 react-native link
-
Hermes 作为可选引擎:提供更好的启动性能和更小的应用体积
-
CocoaPods 成为 iOS 默认的包管理工具
三、跨端通用问题
1. 对比 Flutter、RN、小程序等跨端方案的优劣?
-
RN: 生态成熟,社区活跃,开发体验接近 Web。性能接近原生,但 Bridge 是瓶颈
-
Flutter: 性能极佳(自渲染引擎),UI 一致性最好。但动态化能力弱,包体积大,Dart 语言生态不如 JS
-
小程序: 生态强大,免安装,即用即走。但受平台管控,能力受限,双线程模型通信有开销
2. 你在开发中遇到的最大挑战是什么?如何解决的?
-
小程序:可以谈 setData 性能优化、复杂自定义组件的开发、解决不同机型下的兼容性问题
-
RN:可以谈 Bridge 通信瓶颈的优化、原生模块的开发与调试、内存泄漏问题的排查
总结
这份面试题涵盖了小程序和 React Native 的核心知识点,包括:
小程序重点:
- 双线程模型的设计原理
- setData 的优化策略
- 生命周期管理
- 登录流程
- 组件通信机制
React Native 重点:
- Bridge 通信原理
- 性能优化手段
- Native 模块开发
- 平台适配方案
- 热更新机制
跨端对比:
- 各技术栈的优劣势分析
- 实际开发中的挑战和解决方案
掌握这些知识点,能够帮助你在面试中展现出对跨端开发技术的深入理解和实战经验。