【开源鸿蒙跨平台开发学习笔记】Day03:React Native 开发 HarmonyOS-GitCode口袋工具开发-1

前言

本次参加开源鸿蒙跨平台开发学习活动,选择了 React Native 开发 HarmonyOS技术栈,在学习的同时顺便整理成一份系列笔记,记录从环境到开发的全过程。本篇作为第三篇,重点介绍开发GitCode口袋工具APP的准备和开始阶段。

一、GitCode平台介绍

GitCode是一个专注于开源社区的代码托管平台,提供Git仓库管理、协作开发、CI/CD等全方位服务。作为国内优秀的代码托管平台,GitCode致力于为开发者提供稳定高效的开发环境。

二、本次开发基本思路

使用React Native技术开发HarmonyOS应用,实现GitCode平台的移动端APP。本次使用Axios网络请求库借助GitCode API完成在移动端展示用户信息功能。

用到的Gitcode API:

复制代码
curl "https://api.gitcode.com/api/v5/users/{username}"

网络请求使用Axios库,主要是因为之前从事前端开发工作,对Axios比较熟悉不过它确实有很多地方比ReactNative自带的网络请求有优势的地方:

功能点 Axios 原生 fetch 说明
请求/响应拦截器 ✔ 支持(request、response) ✖ 无,需要手动封装 拦截器可统一处理 token、日志、请求重试等逻辑
自动转换 JSON ✔ 自动将响应 data 转成 JSON ✖ 需手动调用 response.json(),且错误需额外处理 Axios 简化数据解析流程
错误处理 ✔ 统一错误结构(包含状态码、响应等) ✖ 需自写封装,包括 HTTP 错误与网络错误区分 Axios 错误对象更易调试
超时设置 ✔ 直接支持 timeout ✖ 原生不支持,需要自行通过 Promise.race 实现 Axios 带有内置超时机制
取消请求 ✔ 支持 CancelToken / AbortController ✔ 支持 AbortController(新版) 两者都支持,Axios早期就具备
自动携带 Cookie ✔ 支持(含跨域配置) ✖ 需额外设置且实现分散 Axios 默认对 Cookie 处理更规范
上传/下载进度监听 ✔ 支持 onUploadProgressonDownloadProgress ✖ RN 原生 fetch 不支持进度,只能使用其他库 文件上传场景 Axios 更强
请求体序列化 ✔ 自动处理 JSON、FormData、URLSearchParams ✖ 部分格式需手写 Axios 在 POST/PUT 时更便捷
默认配置(BaseURL, headers) ✔ 支持全局默认配置 ✖ 需每次请求传入或自行封装 项目结构更清晰
响应数据层次 ✔ 返回的数据为 { data, status, headers, config } ✖ 需手动解析 headers、状态码等 Axios 信息更集中
浏览器/Node 通用性 ✔ 完全一致 ✖ RN fetch 与浏览器 fetch 有细微差别 迁移代码时 Axios 成本更低
API 风格一致性 axios.get/post/put/... ✖ fetch 参数较长且更底层 Axios 调用更简洁

三、依赖和环境准备

安装axios依赖,没指定版本就安装最新版本。

复制代码
npm install axios

创建一个标准的文件结构:

根据之前文章使用RN的init命令创建了基础模版功能,但是并没有前端代码目录,可以按照我画框的方式创建一个前端目录结构,不强制,可以根据自己的喜好创建和配置,我就按照我目前的目录结构配置了。

我们用AI生成一个ReactNative的helloworld程序测试下:

  1. 对应刚刚创建的文件夹路径配置App.tsx文件;
  2. 创建一套基础的页面带有底部TabBar组件;
  3. 执行npm run dev编译代码;
  4. 在目标产出物文件夹取出编译后的文件这次是Harmony文件夹下的rawfile文件内的文件;
  5. 复制到HarmonyOS工程下的rawfile文件夹下;
  6. 运行到模拟器或者真机;

我在刚开始遇到了一个报错:

查了一下,这个原因是"未进行端口映射导致设备端 localhost:8081 连不到宿主机"需要在HarmonyOS工程根目录下执行HDC命令:"hdc rport tcp:8081 tcp:8081",大家可以根据自己的端口设置下。

好了,我们的测试页面已经可以显示了。O(∩_∩)O哈哈~

四、对接GitCode API

1、第一步生成一个调用API使用的访问令牌,地址:https://gitcode.com/setting/token-classic

2、编写请求:"curl "https://api.gitcode.com/api/v5/users/{username}""接口的代码逻辑;

根据之前我创建的文件目录格式:

复制代码
├── src/                         # 业务代码主目录
│   ├── api/                     # 网络请求层(Axios 封装、接口模块)
│   ├── assets/                  # 静态资源(图片、图标、字体、Lottie 动画等)
│   ├── components/              # 公共 UI 组件(按钮、卡片、头部栏等可复用组件)
│   ├── hooks/                   # 自定义 React Hooks(如 useAuth、useRequest)
│   ├── navigation/              # 导航配置(Stack、Tab、Drawer 路由)
│   ├── screens/                 # 页面(HomeScreen、LoginScreen、DetailScreen)
│   ├── store/                   # 状态管理(Redux/Zustand/MobX 等)
│   └── utils/                   # 工具函数(格式转换、常量、日期工具、权限工具)

所以网络请求就写到api文件夹下,先创建一个user.ts内容如下:

TypeScript 复制代码
import axios from 'axios';
import {UserProfile} from '../types/user';

const URL = 'https://api.gitcode.com/api/v5/users/qiaomu8559968';

export async function fetchUserProfile(): Promise<UserProfile> {
  const res = await axios.get<UserProfile>(URL, {timeout: 10000});
  return res.data;
}

api目录下再创建一个index.ts作为模块导出,内容如下:

TypeScript 复制代码
export * from './user';

然后在screens文件夹下创建Home.ts文件作为我们的首页,内容如下:

TypeScript 复制代码
import React, {useEffect, useState} from 'react';
import {
  View,
  Text,
  StyleSheet,
  Image,
  ActivityIndicator,
  ScrollView,
  Pressable,
  Linking,
} from 'react-native';
import {fetchUserProfile} from '../api';
import {UserProfile} from '../types/user';

export default function Home(): JSX.Element {
  const [data, setData] = useState<UserProfile | null>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string>('');

  useEffect(() => {
    let mounted = true;
    setLoading(true);
    setError('');
    fetchUserProfile()
      .then(d => {
        if (!mounted) {
          return;
        }
        setData(d);
      })
      .catch(e => {
        if (!mounted) {
          return;
        }
        setError(String(e?.message || e));
      })
      .finally(() => {
        if (!mounted) {
          return;
        }
        setLoading(false);
      });
    return () => {
      mounted = false;
    };
  }, []);

  if (loading) {
    return (
      <View style={styles.center}>
        <ActivityIndicator />
        <Text style={styles.loadingText}>加载中</Text>
      </View>
    );
  }

  if (error) {
    return (
      <View style={styles.center}>
        <Text style={styles.errorText}>请求失败:{error}</Text>
      </View>
    );
  }

  if (!data) {
    return (
      <View style={styles.center}>
        <Text style={styles.errorText}>暂无数据</Text>
      </View>
    );
  }

  return (
    <ScrollView contentContainerStyle={styles.scrollContent}>
      <Image source={{uri: data.avatar_url}} style={styles.avatar} />
      <Text style={styles.title}>{data.name || data.login}</Text>
      <Text style={styles.subtitle}>类型:{data.type}</Text>
      <Text style={styles.subtitle}>
        粉丝:{data.followers},关注:{data.following}
      </Text>
      {Boolean(data.bio) && <Text style={styles.bio}>{data.bio}</Text>}
      <Pressable
        onPress={() => Linking.openURL(data.html_url)}
        style={styles.linkButton}>
        <Text style={styles.linkText}>打开主页</Text>
      </Pressable>
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  center: {flex: 1, alignItems: 'center', justifyContent: 'center'},
  loadingText: {marginTop: 8, fontSize: 14, color: '#666'},
  errorText: {fontSize: 14, color: '#d00'},
  scrollContent: {alignItems: 'center', paddingVertical: 24},
  avatar: {width: 120, height: 120, borderRadius: 60, backgroundColor: '#eee'},
  title: {marginTop: 16, fontSize: 24, fontWeight: '700'},
  subtitle: {marginTop: 8, fontSize: 16, color: '#666'},
  bio: {
    marginTop: 12,
    fontSize: 14,
    color: '#333',
    paddingHorizontal: 24,
    textAlign: 'center',
  },
  linkButton: {
    marginTop: 16,
    paddingHorizontal: 16,
    paddingVertical: 10,
    borderRadius: 6,
    backgroundColor: '#007aff',
  },
  linkText: {color: '#fff', fontSize: 14, fontWeight: '600'},
});

然后再编译执行"npm run dev"复制产出物到HarmonyOS工程下,运行APP。

✿✿ヽ(°▽°)ノ✿,好了第一个接口调试通了;

总结

本篇内容主要集中在ReactNative的网络请求和GitCode API调用,后续我们继续优化当前这个应用和网络请求比如拦截器、认证等等。

相关推荐
lqj_本人2 小时前
鸿蒙Cordova开发踩坑记录:震动反馈的“时差“
华为·harmonyos
ouliten3 小时前
C++笔记:std::string_view
开发语言·c++·笔记
lqj_本人4 小时前
鸿蒙原生与Qt混合开发:性能优化与资源管理
qt·harmonyos
lqj_本人4 小时前
鸿蒙Qt字体实战:消灭“豆腐块“乱码与自定义字体加载
qt·华为·harmonyos
爱笑的眼睛115 小时前
深入探索HarmonyOS中RichText组件的HTML渲染机制
华为·harmonyos
IT闫5 小时前
figlet 在鸿蒙PC上的构建与适配
华为·harmonyos
im_AMBER5 小时前
AI井字棋项目开发笔记
前端·笔记·学习·算法
饕餮争锋5 小时前
Spring事件_发布&监听(2)_笔记
java·笔记·spring
zxguan5 小时前
Springboot 学习 之 下载接口 HttpMessageNotWritableException
spring boot·后端·学习