小程序和 React Native 面试题答案

134 阅读6分钟

小程序和 React Native 面试题答案

一、小程序经典面试题

1. 小程序的双线程模型是什么?为什么这么设计?

是什么: 小程序的渲染层(WebView)和逻辑层(JsCore)是分开的,分别在两个线程中运行。

为什么(设计初衷):

  • 安全性:防止开发者操作 DOM/XHR 直接绕过小程序框架的管控,逻辑层无法直接操作视图,必须通过 setData 通知渲染层更新,方便对数据进行安全校验。

  • 性能与体验:逻辑层和渲染层独立运行,即使 JS 逻辑执行繁忙(如计算),也不会阻塞页面的渲染和用户交互,保证了页面的流畅性。同时,多个页面可以共享同一个逻辑线程,减少了资源开销。

2. 请详细说明 setData 的工作原理和优化技巧

工作原理: setData 是连接逻辑层与渲染层的桥梁。调用后,数据会以 JSON.stringify() 后的字符串形式从逻辑层传输到渲染层(Native 做中转),渲染层再通过 JSON.parse() 和 evaluateJavascript() 来更新视图。这是一个异步且开销较大的过程。

优化技巧(必考):

  1. 减少数据量:只 set 发生变化的数据,避免传递超大对象或长数组。
  2. 降低调用频率:合并多次 setData 调用,避免在循环中调用。
  3. 使用路径更新:对于对象或数组的局部更新,使用路径语法。
// 坏
this.setData({ list: newList })

// 好
this.setData({ 'list[0].title': 'New Title' })
  1. 避开与渲染无关的数据:与渲染无关的数据不要放在 data 中,可直接挂在 this 上。

3. 小程序的生命周期函数有哪些?应用和页面有什么区别?

应用生命周期: onLaunch, onShow, onHide, onError (全局性的)

页面生命周期: onLoad, onShow, onReady, onHide, onUnload, onPullDownRefresh, onReachBottom, onShareAppMessage 等 (页面级的)

区别: App 的生命周期管理整个小程序程序的行为,而 Page 的生命周期只管理单个页面的行为。

4. 小程序的登录流程是怎样的?(OAuth)

这是一个非常经典的流程,务必背熟。

  1. 前端调用 wx.login() 获取临时 code
  2. 将 code 发送给开发者服务器
  3. 开发者服务器拿着 code、自己的 appid 和 appsecret 去微信接口服务端换取用户的 openid 和 session_key
  4. 服务器根据 openid 生成一个自定义的登录态(例如一个 Token),返回给前端
  5. 前端存储这个 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 进行传递,并会被批量处理以提高性能。

  • 三个线程

    1. JS 线程:执行 JavaScript 代码
    2. Native/UI 线程:负责原生 UI 的渲染和用户交互
    3. 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 模块开发
  • 平台适配方案
  • 热更新机制

跨端对比:

  • 各技术栈的优劣势分析
  • 实际开发中的挑战和解决方案

掌握这些知识点,能够帮助你在面试中展现出对跨端开发技术的深入理解和实战经验。