React Native快速入门:构建你的第一个APP

后端App
2025-12-18 21:32
阅读 3838

上周五晚上,我正窝在MacBook前用Cursor敲着一个Node.js中间件——没错,作为一个重度Cursor用户,我已经离不开这个AI搭档了。自从两年前加入这个组,从写纯前端到搞混合开发,再到如今天天和原生桥接打交道,我的键盘都快磨出火星子了。但那天,产品老大突然甩来一句话:“下周三前,搞个iOS和Android都能跑的Demo给客户看,React Native,你行的。” 我差点把手中的冰美式喷出来。

被逼上梁山,不如顺势起飞。


其实我对RN(React Native)早有耳闻,但一直没动真格。毕竟在我们这种“能用Web就不用App”的团队里,移动端优先级常年垫底。直到去年双11期间,我们的H5页面在低端安卓机上白屏三秒,产品经理当场暴走:“用户体验!知道什么叫用户体验吗?!” 于是,跨端原生渲染成了政治正确。而我,这个平时只用Mac写代码、Windows仅用于测试(还经常蓝屏)的底层原理爱好者,被迫扛起了这面大旗。

踩坑初体验:从“Hello World”到“WTF”

初始化项目时,我以为就是 npx react-native init MyApp 一气呵成。结果光是Xcode版本、Android SDK路径、Node版本冲突就折腾了两小时。最离谱的是,模拟器启动后直接报错:

Invariant Violation: "main" has not been registered.

我当场愣住——这不就是最基础的模板吗?后来才发现,是因为我同时开了Metro服务和旧项目的终端,端口冲突导致打包失败。重启大法好,但内心已经想砸键盘。

不过话说回来,一旦跑起来,那丝滑感真香。JSX写界面,热重载秒级反馈,比我在Xcode里改个颜色要等编译三分钟强太多。而且,得益于React的组件化思维,UI拆分特别自然。

写个真实的“产品”:天气小助手

为了不被产品经理再吐槽“Demo太假”,我决定做个稍微像样的功能:一个根据定位显示当地天气的小应用。虽然简单,但涉及权限、网络请求、平台适配,够练手了。

第一步:初始化 + 权限配置

npx react-native init WeatherBuddy

然后,分别处理iOS和Android的定位权限。

iOS:在 ios/WeatherBuddy/Info.plist 中添加:

<key>NSLocationWhenInUseUsageDescription</key>
<string>需要获取位置以显示当地天气</string>

Android:在 android/app/src/main/AndroidManifest.xml 添加:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

这里有个坑:Android 12+ 需要用 ACCESS_COARSE_LOCATION + ACCESS_FINE_LOCATION 双权限,否则 getCurrentPosition 直接静默失败。我当时调试半天才发现日志里有一行小字:“denied due to missing coarse permission”。运维同事路过看了一眼说:“你这不就是典型的权限降级失败嘛?” 我:……谢谢,现在我知道了。

第二步:核心逻辑实现

我用了 @react-native-community/geolocation 获取位置,配合 axios 请求免费天气API(别问,问就是经费有限)。

// components/WeatherCard.tsx
import Geolocation from '@react-native-community/geolocation';
import axios from 'axios';

const WeatherCard = () => {
  const [weather, setWeather] = useState<any>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 请求定位权限(省略权限检查逻辑)
    Geolocation.getCurrentPosition(
      async (position) => {
        const { latitude, longitude } = position.coords;
        try {
          const res = await axios.get(
            `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=YOUR_KEY&units=metric`
          );
          setWeather(res.data);
        } catch (err) {
          console.error('天气API炸了', err);
          // 这里应该兜底,比如显示默认城市
        } finally {
          setLoading(false);
        }
      },
      (error) => {
        console.warn('定位失败', error.message);
        setLoading(false);
        // 用户可能拒绝权限,得友好提示
      },
      { enableHighAccuracy: true, timeout: 15000 }
    );
  }, []);

  if (loading) return <Text>正在加载天气...</Text>;
  if (!weather) return <Text>获取天气失败,请重试</Text>;

  return (
    <View style={styles.card}>
      <Text style={styles.city}>{weather.name}</Text>
      <Text style={styles.temp}>{Math.round(weather.main.temp)}°C</Text>
      <Text>{weather.weather[0].description}</Text>
    </View>
  );
};

注意:不要在真实项目里把API Key硬编码! 我这是为了演示。实际应该用环境变量或后端代理,不然你的Key很快会被爬虫刷爆——别问我怎么知道的。

第三步:平台差异处理

RN号称“Learn Once, Write Anywhere”,但现实是“You write once, debug everywhere”。

比如 iOS 的定位弹窗是系统级的,用户点了“仅使用期间允许”就能用;但 Android 上,不同厂商对后台定位限制不同,有的甚至要手动去设置里开“高精度定位”。为此,我专门封装了一个 useLocationPermission Hook,内部根据 Platform.OS 做差异化处理。

还有样式问题。iOS 默认字体是 San Francisco,Android 是 Roboto,字号表现略有差异。我最后统一用 PixelRatio.getFontScale() 微调,再配合 Platform.select:

const styles = StyleSheet.create({
  temp: {
    fontSize: Platform.select({ ios: 48, android: 44 }),
    fontWeight: '600',
  }
});

性能与体验:别让用户觉得“这是个套壳网页”

上线前,测试妹子发来灵魂拷问:“为什么第一次打开要等3秒?你们不是原生吗?”

哦,因为默认的Bundle加载策略是冷启动全量加载。解决方案有两个:

  1. 启用Hermes引擎(RN 0.60+默认开启):大幅减少JS解析时间。
  2. 代码分割 + 懒加载:虽然RN官方不支持动态import,但可以用 React.lazy + 自定义加载器实现模块懒加载。

我在 android/app/build.gradle 确认了Hermes已开启:

project.ext.react = [
    enableHermes: true  // 👈 关键!
]

iOS那边则在 Podfile 里确保 Hermes 被包含:

use_react_native!(
  :hermes_enabled => true
)

实测启动时间从3.2s降到1.4s,测试妹子终于露出了笑容。

发布上架:另一场修行

你以为写完代码就完了?Too young.

  • iOS:要注册Apple Developer账号(99刀/年),配置Provisioning Profile,处理各种证书错误。有一次我换了新Mac,忘了迁移钥匙串,Xcode疯狂报错“no valid signing identities”,差点哭出来。
  • Android:要生成签名APK,配置 keystore.properties,还要过Google Play的审核(比如隐私政策链接)。

我们最后用 eas build(Expo Application Services)简化流程,一条命令云端构建,省去本地环境烦恼。虽然有点贵,但比起自己搭CI/CD,值了。

开发心得:技术分享的终极意义

回过头看,这个小项目从“被逼无奈”到“真香现场”,让我深刻体会到:

  • RN不是银弹,但确实是性价比之选:对于中低复杂度的业务场景(比如我们这种数据展示型App),它能用70%的Web开发效率,达到90%的原生体验。
  • 平台差异永远存在:别信“一次编写到处运行”,做好为两个平台分别调试的心理准备。
  • 工具链决定幸福感:强烈推荐搭配TypeScript + ESLint + Prettier + Cursor。尤其是Cursor,当我写到 Geolocation.getCurrentPosition 时,它自动补全了完整的错误处理回调模板,省下我查文档十分钟。
维度 Web App React Native 原生
开发速度 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐
性能 ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
平台能力 ⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
维护成本 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐

当然,如果你要做高性能游戏或重度动画,还是老老实实写原生吧。但对我们这种“产品需求变比翻书快”的团队来说,RN简直是救命稻草——上周五提的需求,今天就能给客户演示,老板看了直呼“高效”。

所以,别再犹豫了。装好Node、Xcode、Android Studio(祝你好运),然后:

npx react-native init YourFirstApp

然后,让Cursor帮你写第一行代码。相信我,一旦你尝过AI结对编程的甜头,就再也回不去了。


后记:这篇文章写完时,已经是凌晨两点。我合上MacBook,看了眼手机——天气小助手居然还在后台默默跑着,温度显示准确。那一刻,所有的debug痛苦都值得了。毕竟,我们写的不是代码,是产品,是用户手中的体验。

评论 0

最热最新
暂无评论
后端AppLv.1
0
影响力
0
文章
0
粉丝