在 React Native 中进行鸿蒙(HarmonyOS)开发时,由于鸿蒙操作系统是基于华为自家开发的 HarmonyOS 系统,它与 OpenHarmony 系统有一定的相似性,但也存在一些差异。如果你想在 React Native 应用中加入鸿蒙特有的功能或者适配鸿蒙系统,你可以通过以下步骤来实现:

  1. 环境准备

确保你的开发环境支持鸿蒙开发。华为提供了一个 HarmonyOS SDK,你可以通过华为开发者联盟官网下载并集成到你的 React Native 项目中。

  1. 集成 HarmonyOS SDK

  2. 下载 SDK:从华为开发者网站下载 HarmonyOS SDK。

  3. 配置项目:解压 SDK,按照文档指导在你的 React Native 项目中配置 SDK。

  4. 使用鸿蒙特定的组件或API

由于 React Native 主要是基于 OpenHarmony 和 iOS,直接使用鸿蒙特定的组件或 API 可能需要一些额外的步骤。你可以通过以下方式实现:

  • 使用原生模块:你可以创建一个原生模块来调用鸿蒙的特定 API。例如,使用 Java 或 Kotlin 编写一个原生模块,然后在 React Native 中调用它。

    // 在 OpenHarmony 原生模块中
    public class HarmonyModule extends ReactContextBaseJavaModule {
        @ReactMethod
        public void showHarmonyDialog(String message) {
            // 调用鸿蒙特定的对话框API
        }
    }
    

    然后在 React Native 中调用:

    import { NativeModules } from 'react-native';
    const { HarmonyModule } = NativeModules;
    HarmonyModule.showHarmonyDialog('Hello Harmony');
    
  1. 测试和调试

在开发过程中,确保你能够在鸿蒙设备或模拟器上测试你的应用。使用华为提供的开发工具(如 DevEco Studio)来部署和调试你的应用。

  1. 适配鸿蒙特有的功能
  • 暗黑模式适配:确保你的应用能够适配鸿蒙系统的暗黑模式。在 React Native 中,你可以通过修改主题或者使用条件样式来实现。
  • 权限管理:使用鸿蒙的权限管理 API 来请求和检查权限。
  • 多窗口支持:如果你的应用需要支持多窗口,确保你的界面布局和交互能够适应多窗口环境。

真实实际案列演示效果:

import React, { useState } from 'react';
import { View, Text, StyleSheet, ScrollView, Dimensions, TouchableOpacity, Modal, Animated, Easing } from 'react-native';

// Simple Icon Component using Unicode symbols
interface IconProps {
  name: string;
  size?: number;
  color?: string;
  style?: object;
}

const Icon: React.FC<IconProps> = ({ 
  name, 
  size = 24, 
  color = '#333333',
  style 
}) => {
  const getIconSymbol = () => {
    switch (name) {
      case 'success': return '✅';
      case 'error': return '❌';
      case 'warning': return '⚠️';
      case 'info': return 'ℹ️';
      case 'question': return '❓';
      case 'close': return '✕';
      case 'check': return '✓';
      case 'cancel': return '✕';
      case 'delete': return '🗑️';
      case 'edit': return '✏️';
      case 'download': return '📥';
      case 'upload': return '📤';
      default: return 'ℹ️';
    }
  };

  return (
    <View style={[{ width: size, height: size, justifyContent: 'center', alignItems: 'center' }, style]}>
      <Text style={{ fontSize: size * 0.8, color, includeFontPadding: false, textAlign: 'center' }}>
        {getIconSymbol()}
      </Text>
    </View>
  );
};

// Dialog Component
interface DialogProps {
  visible: boolean;
  onClose: () => void;
  title?: string;
  message: string;
  type?: 'alert' | 'confirm' | 'prompt' | 'custom';
  confirmText?: string;
  cancelText?: string;
  onConfirm?: () => void;
  onCancel?: () => void;
  showIcon?: boolean;
  iconType?: 'success' | 'error' | 'warning' | 'info' | 'question';
  actions?: {
    text: string;
    onPress: () => void;
    type?: 'primary' | 'secondary' | 'danger';
  }[];
}

const Dialog: React.FC<DialogProps> = ({ 
  visible, 
  onClose, 
  title, 
  message,
  type = 'alert',
  confirmText = '确定',
  cancelText = '取消',
  onConfirm,
  onCancel,
  showIcon = true,
  iconType = 'info',
  actions
}) => {
  const [scaleAnim] = useState(new Animated.Value(0.8));
  const [opacityAnim] = useState(new Animated.Value(0));

  React.useEffect(() => {
    if (visible) {
      Animated.parallel([
        Animated.timing(scaleAnim, {
          toValue: 1,
          duration: 200,
          easing: Easing.out(Easing.ease),
          useNativeDriver: true
        }),
        Animated.timing(opacityAnim, {
          toValue: 1,
          duration: 200,
          useNativeDriver: true
        })
      ]).start();
    } else {
      Animated.parallel([
        Animated.timing(scaleAnim, {
          toValue: 0.8,
          duration: 150,
          useNativeDriver: true
        }),
        Animated.timing(opacityAnim, {
          toValue: 0,
          duration: 150,
          useNativeDriver: true
        })
      ]).start();
    }
  }, [visible]);

  const getIconColor = () => {
    switch (iconType) {
      case 'success': return '#52c41a';
      case 'error': return '#ff4d4f';
      case 'warning': return '#faad14';
      case 'question': return '#1890ff';
      default: return '#1890ff';
    }
  };

  const handleConfirm = () => {
    onConfirm && onConfirm();
    onClose();
  };

  const handleCancel = () => {
    onCancel && onCancel();
    onClose();
  };

  const renderActions = () => {
    if (actions) {
      return (
        <View style={styles.actionsContainer}>
          {actions.map((action, index) => (
            <TouchableOpacity
              key={index}
              style={[
                styles.actionButton,
                action.type === 'primary' && styles.primaryButton,
                action.type === 'danger' && styles.dangerButton,
                action.type === 'secondary' && styles.secondaryButton,
                index !== actions.length - 1 && styles.actionButtonSeparator
              ]}
              onPress={() => {
                action.onPress();
                onClose();
              }}
            >
              <Text 
                style={[
                  styles.actionButtonText,
                  action.type === 'primary' && styles.primaryButtonText,
                  action.type === 'danger' && styles.dangerButtonText,
                  action.type === 'secondary' && styles.secondaryButtonText
                ]}
              >
                {action.text}
              </Text>
            </TouchableOpacity>
          ))}
        </View>
      );
    }

    switch (type) {
      case 'confirm':
        return (
          <View style={styles.actionsContainer}>
            <TouchableOpacity
              style={[styles.actionButton, styles.secondaryButton]}
              onPress={handleCancel}
            >
              <Text style={[styles.actionButtonText, styles.secondaryButtonText]}>
                {cancelText}
              </Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={[styles.actionButton, styles.primaryButton]}
              onPress={handleConfirm}
            >
              <Text style={[styles.actionButtonText, styles.primaryButtonText]}>
                {confirmText}
              </Text>
            </TouchableOpacity>
          </View>
        );
      default:
        return (
          <TouchableOpacity
            style={[styles.actionButton, styles.primaryButton]}
            onPress={handleConfirm}
          >
            <Text style={[styles.actionButtonText, styles.primaryButtonText]}>
              {confirmText}
            </Text>
          </TouchableOpacity>
        );
    }
  };

  return (
    <Modal
      visible={visible}
      transparent
      animationType="none"
      onRequestClose={onClose}
    >
      <TouchableOpacity 
        style={styles.overlay}
        onPress={type === 'alert' ? handleConfirm : handleCancel}
        activeOpacity={1}
      >
        <Animated.View 
          style={[
            styles.dialogContainer,
            { 
              transform: [{ scale: scaleAnim }],
              opacity: opacityAnim
            }
          ]}
        >
          <View style={styles.dialogContent}>
            {(title || showIcon) && (
              <View style={styles.header}>
                {showIcon && (
                  <Icon 
                    name={iconType} 
                    size={32} 
                    color={getIconColor()} 
                    style={styles.headerIcon}
                  />
                )}
                {title && <Text style={styles.title}>{title}</Text>}
              </View>
            )}
            
            <View style={styles.messageContainer}>
              <Text style={styles.message}>{message}</Text>
            </View>
            
            {renderActions()}
          </View>
        </Animated.View>
      </TouchableOpacity>
    </Modal>
  );
};

// Main App Component
const DialogComponentApp = () => {
  const [alertView, setAlertView] = useState(false);
  const [confirmView, setConfirmView] = useState(false);
  const [warningView, setWarningView] = useState(false);
  const [customView, setCustomView] = useState(false);
  const [multiActionView, setMultiActionView] = useState(false);

  return (
    <ScrollView style={styles.container}>
      <View style={styles.header}>
        <Text style={styles.headerTitle}>弹出框组件</Text>
        <Text style={styles.headerSubtitle}>美观实用的对话框控件</Text>
      </View>
      
      <View style={styles.section}>
        <Text style={styles.sectionTitle}>基础用法</Text>
        <View style={styles.dialogGroupsContainer}>
          <TouchableOpacity 
            style={styles.dialogButton}
            onPress={() => setAlertView(true)}
          >
            <Text style={styles.dialogButtonText}>基础弹出框</Text>
          </TouchableOpacity>
          
          <TouchableOpacity 
            style={styles.dialogButton}
            onPress={() => setConfirmView(true)}
          >
            <Text style={styles.dialogButtonText}>确认弹出框</Text>
          </TouchableOpacity>
          
          <TouchableOpacity 
            style={styles.dialogButton}
            onPress={() => setWarningView(true)}
          >
            <Text style={styles.dialogButtonText}>警告弹出框</Text>
          </TouchableOpacity>
          
          <TouchableOpacity 
            style={styles.dialogButton}
            onPress={() => setCustomView(true)}
          >
            <Text style={styles.dialogButtonText}>自定义弹出框</Text>
          </TouchableOpacity>
          
          <TouchableOpacity 
            style={styles.dialogButton}
            onPress={() => setMultiActionView(true)}
          >
            <Text style={styles.dialogButtonText}>多操作弹出框</Text>
          </TouchableOpacity>
        </View>
      </View>
      
      <View style={styles.section}>
        <Text style={styles.sectionTitle}>应用场景</Text>
        <View style={styles.scenariosContainer}>
          <View style={styles.scenarioCard}>
            <Icon name="info" size={32} color="#1890ff" style={styles.scenarioIcon} />
            <Text style={styles.scenarioTitle}>信息提示</Text>
            <Text style={styles.scenarioDesc}>普通信息展示</Text>
          </View>
          
          <View style={styles.scenarioCard}>
            <Icon name="question" size={32} color="#faad14" style={styles.scenarioIcon} />
            <Text style={styles.scenarioTitle}>操作确认</Text>
            <Text style={styles.scenarioDesc}>重要操作确认</Text>
          </View>
          
          <View style={styles.scenarioCard}>
            <Icon name="error" size={32} color="#ff4d4f" style={styles.scenarioIcon} />
            <Text style={styles.scenarioTitle}>错误提示</Text>
            <Text style={styles.scenarioDesc}>错误信息展示</Text>
          </View>
        </View>
      </View>
      
      <View style={styles.section}>
        <Text style={styles.sectionTitle}>功能演示</Text>
        <View style={styles.demosContainer}>
          <View style={styles.demoItem}>
            <Icon name="info" size={24} color="#1890ff" style={styles.demoIcon} />
            <View>
              <Text style={styles.demoTitle}>多种类型</Text>
              <Text style={styles.demoDesc}>支持信息、确认、警告等多种类型</Text>
            </View>
          </View>
          
          <View style={styles.demoItem}>
            <Icon name="check" size={24} color="#52c41a" style={styles.demoIcon} />
            <View>
              <Text style={styles.demoTitle}>图标支持</Text>
              <Text style={styles.demoDesc}>内置多种状态图标</Text>
            </View>
          </View>
          
          <View style={styles.demoItem}>
            <Icon name="question" size={24} color="#faad14" style={styles.demoIcon} />
            <View>
              <Text style={styles.demoTitle}>自定义操作</Text>
              <Text style={styles.demoDesc}>支持自定义按钮和操作</Text>
            </View>
          </View>
        </View>
      </View>
      
      <View style={styles.usageSection}>
        <Text style={styles.sectionTitle}>使用方法</Text>
        <View style={styles.codeBlock}>
          <Text style={styles.codeText}>{'<Dialog'}</Text>
          <Text style={styles.codeText}>  visible={'{isVisible}'}</Text>
          <Text style={styles.codeText}>  onClose={'{setVisible}'}</Text>
          <Text style={styles.codeText}>  title="标题"</Text>
          <Text style={styles.codeText}>  message="内容信息"{'\n'}/></Text>
        </View>
        <Text style={styles.description}>
          Dialog组件提供了完整的弹出框功能,包括信息提示、操作确认、警告提示等。
          通过visible控制显示状态,onClose处理关闭事件,支持自定义标题、内容和操作按钮。
        </Text>
      </View>
      
      <View style={styles.featuresSection}>
        <Text style={styles.sectionTitle}>功能特性</Text>
        <View style={styles.featuresList}>
          <View style={styles.featureItem}>
            <Icon name="info" size={20} color="#1890ff" style={styles.featureIcon} />
            <Text style={styles.featureText}>多种类型</Text>
          </View>
          <View style={styles.featureItem}>
            <Icon name="check" size={20} color="#52c41a" style={styles.featureIcon} />
            <Text style={styles.featureText}>图标支持</Text>
          </View>
          <View style={styles.featureItem}>
            <Icon name="question" size={20} color="#faad14" style={styles.featureIcon} />
            <Text style={styles.featureText}>自定义操作</Text>
          </View>
          <View style={styles.featureItem}>
            <Icon name="error" size={20} color="#ff4d4f" style={styles.featureIcon} />
            <Text style={styles.featureText}>状态反馈</Text>
          </View>
        </View>
      </View>
      
      <View style={styles.footer}>
        <Text style={styles.footerText}>© 2023 弹出框组件 | 现代化UI组件库</Text>
      </View>
      
      {/* Dialogs */}
      <Dialog
        visible={alertView}
        onClose={() => setAlertView(false)}
        title="信息提示"
        message="这是一个基础的信息提示弹出框,用于向用户展示重要信息。"
        iconType="info"
        onConfirm={() => console.log('Alert confirmed')}
      />
      
      <Dialog
        visible={confirmView}
        onClose={() => setConfirmView(false)}
        title="操作确认"
        message="您确定要执行此操作吗?此操作无法撤销。"
        type="confirm"
        iconType="question"
        onConfirm={() => console.log('Confirmed')}
        onCancel={() => console.log('Cancelled')}
      />
      
      <Dialog
        visible={warningView}
        onClose={() => setWarningView(false)}
        title="警告提示"
        message="您的操作可能导致数据丢失,请谨慎操作!"
        iconType="warning"
        type="confirm"
        confirmText="继续操作"
        cancelText="取消"
        onConfirm={() => console.log('Warning confirmed')}
        onCancel={() => console.log('Warning cancelled')}
      />
      
      <Dialog
        visible={customView}
        onClose={() => setCustomView(false)}
        title="自定义操作"
        message="您可以自定义弹出框的按钮和操作,满足不同的业务需求。"
        iconType="success"
        actions={[
          { 
            text: '查看详情', 
            onPress: () => console.log('View details'), 
            type: 'secondary' 
          },
          { 
            text: '立即处理', 
            onPress: () => console.log('Handle now'), 
            type: 'primary' 
          }
        ]}
      />
      
      <Dialog
        visible={multiActionView}
        onClose={() => setMultiActionView(false)}
        title="多操作选择"
        message="请选择您要执行的操作,不同的操作会产生不同的结果。"
        iconType="question"
        actions={[
          { 
            text: '编辑', 
            onPress: () => console.log('Edit'), 
            type: 'secondary' 
          },
          { 
            text: '下载', 
            onPress: () => console.log('Download'), 
            type: 'secondary' 
          },
          { 
            text: '删除', 
            onPress: () => console.log('Delete'), 
            type: 'danger' 
          }
        ]}
      />
    </ScrollView>
  );
};

const { width, height } = Dimensions.get('window');

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fffbe6',
  },
  header: {
    backgroundColor: '#ffffff',
    paddingVertical: 30,
    paddingHorizontal: 20,
    marginBottom: 10,
    borderBottomWidth: 1,
    borderBottomColor: '#f0f0f0',
  },
  headerTitle: {
    fontSize: 28,
    fontWeight: '700',
    color: '#d46b08',
    textAlign: 'center',
    marginBottom: 5,
  },
  headerSubtitle: {
    fontSize: 16,
    color: '#d4883a',
    textAlign: 'center',
  },
  section: {
    marginBottom: 25,
  },
  sectionTitle: {
    fontSize: 20,
    fontWeight: '700',
    color: '#d46b08',
    paddingHorizontal: 20,
    paddingBottom: 15,
  },
  dialogGroupsContainer: {
    backgroundColor: '#ffffff',
    marginHorizontal: 15,
    borderRadius: 12,
    padding: 20,
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 4,
    marginBottom: 10,
  },
  dialogButton: {
    backgroundColor: '#fff5e6',
    borderRadius: 8,
    paddingVertical: 15,
    paddingHorizontal: 20,
    marginBottom: 15,
    borderWidth: 1,
    borderColor: '#ffd699',
  },
  dialogButtonLast: {
    marginBottom: 0,
  },
  dialogButtonText: {
    fontSize: 16,
    color: '#d46b08',
    fontWeight: '500',
    textAlign: 'center',
  },
  scenariosContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    paddingHorizontal: 15,
  },
  scenarioCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 20,
    width: (width - 60) / 3,
    alignItems: 'center',
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 4,
  },
  scenarioIcon: {
    marginBottom: 15,
  },
  scenarioTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#5a3b1c',
    marginBottom: 5,
  },
  scenarioDesc: {
    fontSize: 14,
    color: '#d4883a',
    textAlign: 'center',
  },
  demosContainer: {
    backgroundColor: '#ffffff',
    marginHorizontal: 15,
    borderRadius: 15,
    padding: 20,
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 4,
  },
  demoItem: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 20,
  },
  demoItemLast: {
    marginBottom: 0,
  },
  demoIcon: {
    marginRight: 15,
  },
  demoTitle: {
    fontSize: 16,
    fontWeight: '600',
    color: '#5a3b1c',
    marginBottom: 3,
  },
  demoDesc: {
    fontSize: 14,
    color: '#d4883a',
  },
  usageSection: {
    backgroundColor: '#ffffff',
    marginHorizontal: 15,
    borderRadius: 15,
    padding: 20,
    marginBottom: 20,
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 4,
  },
  codeBlock: {
    backgroundColor: '#4b2e1e',
    borderRadius: 8,
    padding: 15,
    marginBottom: 15,
  },
  codeText: {
    fontFamily: 'monospace',
    color: '#f5e4d7',
    fontSize: 14,
    lineHeight: 22,
  },
  description: {
    fontSize: 15,
    color: '#8c6a4d',
    lineHeight: 22,
  },
  featuresSection: {
    backgroundColor: '#ffffff',
    marginHorizontal: 15,
    borderRadius: 15,
    padding: 20,
    marginBottom: 20,
    elevation: 3,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.08,
    shadowRadius: 4,
  },
  featuresList: {
    paddingLeft: 10,
  },
  featureItem: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 15,
  },
  featureIcon: {
    marginRight: 15,
  },
  featureText: {
    fontSize: 16,
    color: '#5a3b1c',
  },
  footer: {
    paddingVertical: 20,
    alignItems: 'center',
  },
  footerText: {
    color: '#d4b58a',
    fontSize: 14,
  },
  // Dialog Styles
  overlay: {
    flex: 1,
    backgroundColor: 'rgba(0, 0, 0, 0.6)',
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  dialogContainer: {
    width: '100%',
    maxWidth: 350,
  },
  dialogContent: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    overflow: 'hidden',
    elevation: 10,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 5 },
    shadowOpacity: 0.3,
    shadowRadius: 10,
  },
  header: {
    alignItems: 'center',
    padding: 25,
    paddingBottom: 15,
  },
  headerIcon: {
    marginBottom: 15,
  },
  title: {
    fontSize: 20,
    fontWeight: '700',
    color: '#5a3b1c',
    textAlign: 'center',
  },
  messageContainer: {
    paddingHorizontal: 25,
    paddingBottom: 25,
  },
  message: {
    fontSize: 16,
    color: '#8c6a4d',
    textAlign: 'center',
    lineHeight: 24,
  },
  actionsContainer: {
    flexDirection: 'row',
    borderTopWidth: 1,
    borderTopColor: '#f0f0f0',
  },
  actionButton: {
    flex: 1,
    paddingVertical: 18,
    alignItems: 'center',
    justifyContent: 'center',
  },
  primaryButton: {
    backgroundColor: '#d46b08',
  },
  secondaryButton: {
    backgroundColor: '#ffffff',
  },
  dangerButton: {
    backgroundColor: '#ff4d4f',
  },
  actionButtonSeparator: {
    borderRightWidth: 1,
    borderRightColor: '#f0f0f0',
  },
  actionButtonText: {
    fontSize: 16,
    fontWeight: '600',
  },
  primaryButtonText: {
    color: '#ffffff',
  },
  secondaryButtonText: {
    color: '#d46b08',
  },
  dangerButtonText: {
    color: '#ffffff',
  },
});

export default DialogComponentApp;

从鸿蒙ArkUI开发角度深入分析这段React Native Dialog组件的代码逻辑:

该Dialog组件在鸿蒙中对应着CustomDialogController的实现模式,通过@State装饰器管理visible状态来控制对话框的显示与隐藏。当visible状态变更时,触发useEffect中的动画逻辑,这与鸿蒙的aboutToAppear和aboutToDisappear生命周期函数的作用相似。

动画系统采用Animated API实现复合动画效果,scaleAnim控制缩放变换,opacityAnim控制透明度变化。Animated.parallel实现多个动画的同步执行,Easing.out(Easing.ease)对应鸿蒙的Curve.EaseOut插值器。useNativeDriver设置为true表明启用原生动画驱动,这与鸿蒙的动画硬件加速机制对应。

Icon组件通过Unicode符号映射实现图标显示,getIconSymbol方法中的switch-case逻辑对应鸿蒙的图标资源管理。在鸿蒙中,图标通过Symbol组件显示,支持系统图标和自定义图标资源。getIconColor函数根据iconType返回对应的主题色,这与鸿蒙的动态主题色系统设计一致。

在这里插入图片描述

组件采用条件渲染策略,通过renderActions函数动态生成操作按钮区域。当actions数组存在时,采用map方法遍历渲染自定义操作按钮;否则根据type参数渲染默认的确认/取消按钮组合。这种设计模式在鸿蒙中通过@Builder装饰器实现类似的动态UI构建能力。

事件处理机制通过handleConfirm和handleCancel函数封装业务逻辑,确保在触发回调后自动调用onClose关闭对话框。这种设计保证了对话框状态的一致性,避免出现状态不同步的问题。

状态管理采用受控组件模式,所有状态变更都通过props传递,这与鸿蒙的@Prop装饰器数据流设计理念相符。组件支持多种对话框类型(alert/confirm/prompt/custom),通过type参数控制不同的交互模式。

布局结构采用Modal作为根容器,实现独立的渲染层级和背景遮罩。Animated.View承载对话框内容,通过transform和opacity样式属性绑定动画值,实现流畅的入场和退场动画效果。


打包

接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

在这里插入图片描述

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

在这里插入图片描述

最后运行效果图如下显示:

请添加图片描述

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐