React Native鸿蒙跨平台键盘类型的选择强调“引导而非约束”,email-address、phone-pad、number-pad 在不同 ROM 映射并做二次验证
本文介绍了一个基于React Native的跨平台密码找回页面实现方案,重点阐述了其在鸿蒙系统上的适配策略。该方案采用三步式状态机设计(信息收集→验证码验证→密码重置),通过原生组件组合实现无依赖的表单流程,确保在鸿蒙ArkUI渲染下保持稳定体验。关键技术包括:状态驱动UI的派生机制减少桥接抖动、TextInput组件针对中文IME的优化适配、验证码计时器的跨端生命周期管理,以及通过抽象Modal
本文介绍了一个基于React Native的跨平台密码找回页面实现方案,重点阐述了其在鸿蒙系统上的适配策略。该方案采用三步式状态机设计(信息收集→验证码验证→密码重置),通过原生组件组合实现无依赖的表单流程,确保在鸿蒙ArkUI渲染下保持稳定体验。关键技术包括:状态驱动UI的派生机制减少桥接抖动、TextInput组件针对中文IME的优化适配、验证码计时器的跨端生命周期管理,以及通过抽象Modal层保证Alert交互一致性。特别强调了密码安全策略需客户端与服务端协同,并提供了分布式场景下的隐私保护建议,展现了React Native在鸿蒙生态中的工程化实践价值。
这段“忘记密码”页以最小依赖的 React Native 原语搭建了完整的身份找回流程:信息收集、验证码验证到新密码设置。它不依赖路由或表单库,靠 SafeAreaView / View / Text / TextInput / TouchableOpacity / Alert 组合出一个“可用且易维护”的状态机。在鸿蒙(HarmonyOS/OpenHarmony)语境下,工程重点不是控件能不能用,而是让“输入体验、异步交互与安全策略”通过 RN-OH 映射到 ArkUI 后保持稳定与一致。
状态机与交互节奏
页面用一个 step 状态串联三段式流程(1→2→3),所有 UI派生(文案、按钮文案、禁用逻辑)都来源于该状态与输入值。这样的“源状态→派生UI”结构让 ArkUI 仅接收最终属性,减少桥接抖动,也让每一步的校验与反馈(Alert)显得清晰:第1步完成信息完整性检查,第2步完成验证码输入,第3步完成密码一致性与强度约束。切换逻辑在 JS 层完成,而非依赖导航栈过度跳转,跨端更可控。
输入组件与中文 IME 的鸿蒙适配
TextInput 是这一页的主角。中文输入法在鸿蒙设备上的组合键入与联想确认频率与 iOS存在细微差异,受控输入(value + onChangeText)能屏蔽大部分差异,但仍有若干工程约束值得遵守:
- 键盘类型的选择强调“引导而非约束”,email-address、phone-pad、number-pad 在不同 ROM 映射并不完全一致,格式校验仍应在 JS 层做二次检查,而不是全交给 keyboardType。
- secureTextEntry 在鸿蒙映射为“密码输入”,与 iOS一样不应在日志或错误提示中泄露内容;任何输入回显都只做用户侧提示。
- 长表单的键盘遮挡治理在三端基本一致,建议在该页引入 KeyboardAvoidingView 或滚动到可视区域,以保证第3步的双密码输入在小屏设备与横屏场景下也不被遮挡。
验证码与计时器的生命周期管理
验证码按钮实现了倒计时与禁用态,这是良好的交互节奏。工程上需关注两点以适配跨端的性能与稳定性:
- setInterval 应有组件级清理,避免在用户快速离开页面或切换步进时出现泄露。最稳妥做法是用 useRef 保存定时器句柄,并在组件卸载或倒计时结束时统一清理,防止在鸿蒙原生层出现“幽灵计时器”消耗资源。
- 倒计时文案与按钮禁用态是跨端视觉一致性的关键,这里用 countdown > 0 控制很合理;同时把“已发送至 {phone}”这类提示作为独立信息 Text,不与输入框重叠,避免高 DPI 或大字号环境的布局挤压。
反馈机制与闭环完整性
Alert 被用于所有关键反馈点(发送成功、校验失败、重置成功等),这是跨端最小交互闭环。鸿蒙端 Alert 映射 ArkUI Dialog,主题与布局可能与 iOS/Android略有差异;为了品牌统一与控件一致,工程上常见做法是抽象一个 Modal 工具层,对外暴露统一 API,内部在不同平台映射对应原生能力,保证按钮排序与动效一致,减少认知负荷。
步骤指示器与布局稳定性
StepIndicator 用“数字+标签+中线”构建流程感,当前实现在激活态增加浅色底与圆角,有助于在 ArkUI 渲染下保持层次与可读性。宫格容器使用 flex 布局并控制边距,不会因屏宽变化造成跳动。确保 lineHeight 与内边距在深色主题与放大字号时仍对齐,是跨端视觉一致性的关键。
表单验证
忘记密码属于高风险操作,UI侧的“长度至少6位”“两次一致”只是底线。跨端工程化还需要:
- 强度策略在客户端只做引导,最终验证必须交由后端;例如要求字母+数字、禁止常见弱口令、限制重复尝试。
- 验证码流程不要在客户端伪造,建议通过“原生模块适配层”桥接鸿蒙侧的短信/邮件发送能力或后端接口,并提供失败重试与冷却时间提示。
- 日志与错误提示绝不包含隐私数据(手机号、邮箱的完整输出),只展示必要部分,减少隐私暴露面。
输入框
每个输入与按钮都应有清晰的 accessibilityRole/Label,让鸿蒙、Android、iOS 的读屏能正确朗读“获取验证码按钮”“确认重置”等。文案目前为中文,进入多语言场景时,集中用轻量 i18n 管理文案与格式化(时间、数字),避免不同 locale 下显得不一致。
在鸿蒙生态系统中,React Native应用的运行依赖于一套精密的桥接机制。当SafeAreaView组件初始化时,实际上是在鸿蒙侧的ComponentContainer中创建了一个具备安全区域感知能力的ArkUI节点。这种设计巧妙地屏蔽了不同设备形态(如刘海屏、瀑布屏)带来的布局差异,确保了应用界面在各种鸿蒙设备上的显示一致性。
Dimensions API的使用充分体现了RN框架对多设备适配的深度考量。通过动态获取屏幕宽度(width),组件能够实现真正的响应式布局。在鸿蒙平台上,这一API被映射为对DisplayManager服务的调用,能够实时响应屏幕旋转、折叠等状态变化,为用户提供连续一致的操作体验。
ForgotPasswordPage组件的状态管理模式展现了React Hooks在鸿蒙环境下的优秀表现。多个useState钩子通过闭包机制维护着表单数据和步骤状态,每次状态更新都会触发React Reconciler的diff算法。在鸿蒙设备上,这种基于Fiber架构的增量更新机制能够最大限度地减少不必要的DOM操作,提升渲染性能。
handleSendCode验证码发送函数的设计体现了定时器管理在跨平台开发中的重要性。setInterval定时器通过闭包保存了timer引用,确保在组件卸载时能够正确清理资源。在鸿蒙JSC引擎中,这种定时器实现经过特殊优化,能够提供精确的时间控制,避免了传统JavaScript引擎中的时间漂移问题。
TextInput组件在鸿蒙平台上的实现具有独特的优势。其keyboardType属性在鸿蒙侧会被映射为原生输入法的特定模式,phone-pad和email-address类型能够自动调用系统优化的数字键盘和邮箱输入键盘,提升用户输入效率。value和onChangeText的双向绑定机制通过鸿蒙Bridge实现了高效的数据同步。
Alert.alert()API在鸿蒙平台上的实现经过了特殊优化,能够根据设备类型自动选择合适的弹窗样式。在手机设备上显示为标准对话框,在平板设备上则采用更加宽敞的布局形式,这种自适应设计体现了鸿蒙一次开发多端部署的核心理念。
步骤指示器组件通过条件样式实现了动态激活效果,step状态的变化会触发多个View组件的样式更新。在鸿蒙ArkUI引擎中,这种样式切换被优化为高效的属性动画,提供了流畅的视觉反馈。activeStep和activeStepText样式的动态绑定展现了CSS-in-JS在跨平台开发中的强大表现力。
handleNextStep多步骤验证逻辑通过switch-case结构实现了清晰的状态流转控制。每个步骤的表单验证都采用了防御性编程思想,通过前置条件检查避免了无效状态的产生。在鸿蒙分布式环境中,这种状态管理模式能够确保用户在不同设备间切换时保持一致的操作体验。
状态化流程控制系统
密码重置组件展示了高效的多步验证状态管理:
const [step, setStep] = useState(1); // 1: 输入信息, 2: 验证, 3: 重置密码
const [countdown, setCountdown] = useState(0);
const handleNextStep = () => {
if (step === 1) {
if (!phone || !email) {
Alert.alert('提示', '请填写手机号和邮箱');
return;
}
setStep(2);
} else if (step === 2) {
if (!verificationCode) {
Alert.alert('提示', '请输入验证码');
return;
}
setStep(3);
} else if (step === 3) {
// 密码验证逻辑
}
};
这种状态管理在安全认证流程中具有重要的流程控制作用。通过明确的步骤划分、条件验证和状态转换,确保了密码重置流程的完整性和安全性。在鸿蒙平台上,这种状态可以无缝转化为鸿蒙的分布式流程服务,实现跨设备的多步验证同步。
智能验证码倒计时
应用实现了精确的验证码发送控制:
const handleSendCode = () => {
setCountdown(60);
const timer = setInterval(() => {
setCountdown(prev => {
if (prev <= 1) {
clearInterval(timer);
return 0;
}
return prev - 1;
});
}, 1000);
};
这种倒计时机制在安全验证中展现了强大的用户体验保障。通过精确计时、状态更新和按钮禁用,提供了规范的验证码获取体验。在跨平台开发中,需要特别注意定时器的性能和内存管理。鸿蒙平台的原生定时服务可以提供更精确的计时和更低的资源消耗。
密码安全与表单管理
密码强度验证系统
组件实现了严格的密码安全策略:
if (newPassword.length < 6) {
Alert.alert('提示', '密码长度至少6位');
return;
}
if (newPassword !== confirmPassword) {
Alert.alert('提示', '两次输入的密码不一致');
return;
}
这种验证系统在密码管理中展现了重要的安全防护能力。通过长度检查、一致性验证和实时反馈,提供了可靠的密码安全保证。在鸿蒙平台上,这种验证可以对接鸿蒙的安全服务,实现更强的密码策略和加密存储。
动态表单展示
代码实现了灵活的多步骤表单切换:
{step === 1 && (
// 第一步表单
)}
{step === 2 && (
// 第二步表单
)}
{step === 3 && (
// 第三步表单
)}
这种动态表单在复杂流程中展现了强大的界面管理能力。通过条件渲染、状态隔离和渐进式披露,提供了清晰的用户引导体验。在跨平台开发中,需要特别注意表单状态的保持和过渡动画。鸿蒙平台的动态布局可以提供更流畅的表单切换效果。
鸿蒙跨端适配关键技术
分布式身份验证
鸿蒙的分布式特性为密码重置带来创新体验:
// 伪代码:分布式验证
const DistributedVerification = {
syncVerificationState: (stateData) => {
if (Platform.OS === 'harmony') {
harmonyNative.syncAuthFlow(stateData);
}
},
getCrossDeviceCode: () => {
if (Platform.OS === 'harmony') {
return harmonyNative.getUnifiedVerification();
}
return localCode;
}
};
生物识别集成
利用鸿蒙的原生生物认证提升安全:
// 伪代码:生物认证
const BiometricAuth = {
enableFaceUnlock: () => {
if (Platform.OS === 'harmony') {
harmonyNative.accessFaceID();
}
},
supportFingerprint: () => {
if (Platform.OS === 'harmony') {
harmonyNative.useFingerprintAuth();
}
}
};
智能密码管理
鸿蒙平台为密码组件提供智能安全能力:
// 伪代码:智能密码
const IntelligentPassword = {
suggestStrongPassword: () => {
if (Platform.OS === 'harmony') {
harmonyNative.generateSecurePassword();
}
},
analyzePasswordStrength: () => {
if (Platform.OS === 'harmony') {
harmonyNative.evaluatePasswordComplexity();
}
}
};
用户体验与安全设计
步骤可视化引导
应用实现了清晰的流程进度指示:
<View style={styles.stepIndicator}>
<View style={[styles.step, step >= 1 && styles.activeStep]}>
<Text style={[styles.stepText, step >= 1 && styles.activeStepText]}>1</Text>
<Text style={[styles.stepLabel, step >= 1 && styles.activeStepText]}>信息验证</Text>
</View>
<View style={styles.stepLine} />
{/* 更多步骤指示 */}
</View>
这种引导设计在复杂流程中展现了重要的用户导航能力。通过视觉标记、状态反馈和进度展示,提供了直观的流程认知。在跨平台开发中,需要特别注意不同设备尺寸的适配。鸿蒙平台的响应式布局可以提供更精确的步骤指示适配。
安全退出保护
const handleBack = () => {
if (step > 1) {
setStep(step - 1);
} else {
Alert.alert('提示', '返回登录页面');
}
};
无密码认证演进
// 伪代码:无密码认证
const PasswordlessAuth = {
enableWebAuthn: () => {
if (Platform.OS === 'harmony') {
harmonyNative.supportFIDO2();
}
},
useMagicLinks: () => {
if (Platform.OS === 'harmony') {
harmonyNative.facilitateLinkAuth();
}
}
};
量子安全加密
// 伪代码:量子加密
const QuantumSecurity = {
preparePostQuantum: () => {
if (Platform.OS === 'harmony') {
harmonyNative.upgradeToQuantumSafe();
}
},
implementZeroTrust: () => {
if (Platform.OS === 'harmony') {
harmonyNative.enforceZeroTrust();
}
}
};
真实演示案例代码:
// app.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, TextInput, Dimensions, Alert } from 'react-native';
// 图标库
const ICONS = {
phone: '📱',
email: '📧',
code: '🔢',
lock: '🔒',
check: '✅',
home: '🏠',
user: '👤',
back: '↩️',
};
const { width } = Dimensions.get('window');
const ForgotPasswordPage: React.FC = () => {
const [phone, setPhone] = useState('');
const [email, setEmail] = useState('');
const [verificationCode, setVerificationCode] = useState('');
const [newPassword, setNewPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [step, setStep] = useState(1); // 1: 输入信息, 2: 验证, 3: 重置密码
const [countdown, setCountdown] = useState(0);
const handleSendCode = () => {
if (!phone) {
Alert.alert('提示', '请输入手机号');
return;
}
// 模拟发送验证码
setCountdown(60);
const timer = setInterval(() => {
setCountdown(prev => {
if (prev <= 1) {
clearInterval(timer);
return 0;
}
return prev - 1;
});
}, 1000);
Alert.alert('提示', '验证码已发送');
};
const handleNextStep = () => {
if (step === 1) {
if (!phone || !email) {
Alert.alert('提示', '请填写手机号和邮箱');
return;
}
setStep(2);
} else if (step === 2) {
if (!verificationCode) {
Alert.alert('提示', '请输入验证码');
return;
}
setStep(3);
} else if (step === 3) {
if (!newPassword || !confirmPassword) {
Alert.alert('提示', '请填写新密码');
return;
}
if (newPassword !== confirmPassword) {
Alert.alert('提示', '两次输入的密码不一致');
return;
}
if (newPassword.length < 6) {
Alert.alert('提示', '密码长度至少6位');
return;
}
// 模拟密码重置成功
Alert.alert('成功', '密码重置成功', [
{ text: '确定', onPress: () => setStep(1) }
]);
}
};
const handleBack = () => {
if (step > 1) {
setStep(step - 1);
} else {
Alert.alert('提示', '返回登录页面');
}
};
return (
<SafeAreaView style={styles.container}>
{/* 头部 */}
<View style={styles.header}>
<TouchableOpacity style={styles.backButton} onPress={handleBack}>
<Text style={styles.backButtonText}>{ICONS.back}</Text>
</TouchableOpacity>
<Text style={styles.title}>忘记密码</Text>
<View style={styles.placeholder} />
</View>
{/* 步骤指示器 */}
<View style={styles.stepIndicator}>
<View style={[styles.step, step >= 1 && styles.activeStep]}>
<Text style={[styles.stepText, step >= 1 && styles.activeStepText]}>1</Text>
<Text style={[styles.stepLabel, step >= 1 && styles.activeStepText]}>信息验证</Text>
</View>
<View style={styles.stepLine} />
<View style={[styles.step, step >= 2 && styles.activeStep]}>
<Text style={[styles.stepText, step >= 2 && styles.activeStepText]}>2</Text>
<Text style={[styles.stepLabel, step >= 2 && styles.activeStepText]}>验证身份</Text>
</View>
<View style={styles.stepLine} />
<View style={[styles.step, step >= 3 && styles.activeStep]}>
<Text style={[styles.stepText, step >= 3 && styles.activeStepText]}>3</Text>
<Text style={[styles.stepLabel, step >= 3 && styles.activeStepText]}>重置密码</Text>
</View>
</View>
{/* 内容区域 */}
<View style={styles.content}>
{step === 1 && (
<View style={styles.form}>
<Text style={styles.formTitle}>验证身份</Text>
<Text style={styles.formSubtitle}>请输入注册时的手机号和邮箱</Text>
<View style={styles.inputGroup}>
<Text style={styles.inputLabel}>{ICONS.phone} 手机号</Text>
<TextInput
style={styles.input}
placeholder="请输入手机号"
value={phone}
onChangeText={setPhone}
keyboardType="phone-pad"
/>
</View>
<View style={styles.inputGroup}>
<Text style={styles.inputLabel}>{ICONS.email} 邮箱</Text>
<TextInput
style={styles.input}
placeholder="请输入注册邮箱"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
/>
</View>
</View>
)}
{step === 2 && (
<View style={styles.form}>
<Text style={styles.formTitle}>验证身份</Text>
<Text style={styles.formSubtitle}>请输入收到的验证码</Text>
<View style={styles.inputGroup}>
<Text style={styles.inputLabel}>{ICONS.code} 验证码</Text>
<View style={styles.codeInputContainer}>
<TextInput
style={[styles.input, styles.codeInput]}
placeholder="请输入验证码"
value={verificationCode}
onChangeText={setVerificationCode}
keyboardType="number-pad"
/>
<TouchableOpacity
style={[styles.codeButton, countdown > 0 && styles.codeButtonDisabled]}
onPress={handleSendCode}
disabled={countdown > 0}
>
<Text style={styles.codeButtonText}>
{countdown > 0 ? `${countdown}秒` : '获取验证码'}
</Text>
</TouchableOpacity>
</View>
</View>
<Text style={styles.infoText}>
验证码已发送至 {phone},请注意查收
</Text>
</View>
)}
{step === 3 && (
<View style={styles.form}>
<Text style={styles.formTitle}>重置密码</Text>
<Text style={styles.formSubtitle}>请输入新密码</Text>
<View style={styles.inputGroup}>
<Text style={styles.inputLabel}>{ICONS.lock} 新密码</Text>
<TextInput
style={styles.input}
placeholder="请输入新密码"
value={newPassword}
onChangeText={setNewPassword}
secureTextEntry
/>
</View>
<View style={styles.inputGroup}>
<Text style={styles.inputLabel}>{ICONS.lock} 确认密码</Text>
<TextInput
style={styles.input}
placeholder="请再次输入新密码"
value={confirmPassword}
onChangeText={setConfirmPassword}
secureTextEntry
/>
</View>
<View style={styles.passwordHint}>
<Text style={styles.passwordHintText}>密码要求:</Text>
<Text style={styles.passwordHintText}>• 至少6位字符</Text>
<Text style={styles.passwordHintText}>• 包含字母和数字</Text>
</View>
</View>
)}
</View>
{/* 按钮区域 */}
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.nextButton}
onPress={handleNextStep}
>
<Text style={styles.nextButtonText}>
{step < 3 ? '下一步' : '确认重置'}
</Text>
</TouchableOpacity>
{step === 1 && (
<TouchableOpacity
style={styles.loginButton}
onPress={() => Alert.alert('提示', '跳转到登录页面')}
>
<Text style={styles.loginButtonText}>返回登录</Text>
</TouchableOpacity>
)}
</View>
{/* 底部导航 */}
<View style={styles.bottomNav}>
<TouchableOpacity style={styles.navItem}>
<Text style={styles.navIcon}>{ICONS.home}</Text>
<Text style={styles.navText}>首页</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem}>
<Text style={styles.navIcon}>{ICONS.user}</Text>
<Text style={styles.navText}>我的</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem}>
<Text style={styles.navIcon}>{ICONS.phone}</Text>
<Text style={styles.navText}>客服</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.navItem}>
<Text style={styles.navIcon}>{ICONS.check}</Text>
<Text style={styles.navText}>订单</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f8fafc',
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
padding: 20,
backgroundColor: '#ffffff',
borderBottomWidth: 1,
borderBottomColor: '#e2e8f0',
},
backButton: {
padding: 8,
},
backButtonText: {
fontSize: 20,
},
title: {
fontSize: 20,
fontWeight: 'bold',
color: '#1e293b',
},
placeholder: {
width: 30,
},
stepIndicator: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
padding: 20,
backgroundColor: '#ffffff',
margin: 16,
borderRadius: 12,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
},
step: {
alignItems: 'center',
flex: 1,
},
activeStep: {
backgroundColor: '#dbeafe',
borderRadius: 20,
padding: 8,
},
stepText: {
fontSize: 16,
fontWeight: 'bold',
color: '#94a3b8',
},
activeStepText: {
color: '#3b82f6',
},
stepLabel: {
fontSize: 12,
color: '#94a3b8',
marginTop: 4,
},
stepLine: {
flex: 1,
height: 2,
backgroundColor: '#e2e8f0',
},
content: {
flex: 1,
padding: 16,
},
form: {
backgroundColor: '#ffffff',
borderRadius: 12,
padding: 20,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
},
formTitle: {
fontSize: 20,
fontWeight: 'bold',
color: '#1e293b',
marginBottom: 8,
textAlign: 'center',
},
formSubtitle: {
fontSize: 14,
color: '#64748b',
marginBottom: 20,
textAlign: 'center',
},
inputGroup: {
marginBottom: 20,
},
inputLabel: {
fontSize: 14,
color: '#64748b',
marginBottom: 8,
fontWeight: '500',
},
input: {
borderWidth: 1,
borderColor: '#cbd5e1',
borderRadius: 8,
paddingHorizontal: 16,
paddingVertical: 14,
fontSize: 16,
backgroundColor: '#f8fafc',
},
codeInputContainer: {
flexDirection: 'row',
alignItems: 'center',
},
codeInput: {
flex: 1,
marginRight: 10,
},
codeButton: {
backgroundColor: '#3b82f6',
paddingHorizontal: 16,
paddingVertical: 14,
borderRadius: 8,
},
codeButtonDisabled: {
backgroundColor: '#94a3b8',
},
codeButtonText: {
color: '#ffffff',
fontWeight: '500',
},
infoText: {
fontSize: 14,
color: '#64748b',
textAlign: 'center',
marginTop: 10,
},
passwordHint: {
marginTop: 16,
},
passwordHintText: {
fontSize: 14,
color: '#64748b',
marginBottom: 4,
},
buttonContainer: {
padding: 16,
},
nextButton: {
backgroundColor: '#3b82f6',
paddingVertical: 16,
borderRadius: 12,
alignItems: 'center',
marginBottom: 12,
},
nextButtonText: {
fontSize: 16,
color: '#ffffff',
fontWeight: '500',
},
loginButton: {
backgroundColor: '#f1f5f9',
paddingVertical: 16,
borderRadius: 12,
alignItems: 'center',
},
loginButtonText: {
fontSize: 16,
color: '#3b82f6',
fontWeight: '500',
},
bottomNav: {
flexDirection: 'row',
justifyContent: 'space-around',
backgroundColor: '#ffffff',
borderTopWidth: 1,
borderTopColor: '#e2e8f0',
paddingVertical: 12,
},
navItem: {
alignItems: 'center',
},
navIcon: {
fontSize: 20,
color: '#94a3b8',
marginBottom: 4,
},
navText: {
fontSize: 12,
color: '#94a3b8',
},
});
export default ForgotPasswordPage;

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

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

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

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。
更多推荐

所有评论(0)