ReactNative项目OpenHarmony三方库集成实战:react-native-date-picker
日期选择是移动应用中常见的需求场景,无论是预约服务、填写表单还是记录日程,都离不开直观的日期选择组件。是一个功能丰富的日期选择器库,支持日期、时间、日期时间三种模式,提供模态框和内嵌两种使用方式,让开发者能够轻松实现原生般的日期选择体验。库名称版本信息5.0.6: 支持 RN 0.72 版本(支持 AutoLink)5.1.0: 支持 RN 0.77 版本官方仓库鸿蒙仓库主要功能📅 支持日期、时
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
📋 前言
日期选择是移动应用中常见的需求场景,无论是预约服务、填写表单还是记录日程,都离不开直观的日期选择组件。react-native-date-picker 是一个功能丰富的日期选择器库,支持日期、时间、日期时间三种模式,提供模态框和内嵌两种使用方式,让开发者能够轻松实现原生般的日期选择体验。
🎯 库简介
基本信息
- 库名称:
react-native-date-picker - 版本信息:
5.0.6+@react-native-ohos/react-native-date-picker: 支持 RN 0.72 版本(支持 AutoLink)5.1.0+@react-native-ohos/react-native-date-picker: 支持 RN 0.77 版本
- 官方仓库: https://github.com/henninghall/react-native-date-picker
- 鸿蒙仓库: https://github.com/react-native-oh-library/react-native-date-picker
- 主要功能:
- 📅 支持日期、时间、日期时间三种模式
- 🎛️ 支持模态框和内嵌两种展示方式
- 🎨 丰富的自定义主题和样式
- 🌐 支持多语言和区域设置
- 📱 跨平台一致的用户体验
为什么需要日期选择器?
| 特性 | 原生 DatePicker | react-native-date-picker |
|---|---|---|
| 跨平台一致性 | ❌ Android/iOS 表现不同 | ✅ 统一体验 |
| 交互模式 | ❌ 单一模式 | ✅ 模态框/内嵌任选 |
| 样式定制 | ⚠️ 需要自定义 | ✅ 丰富的配置选项 |
| 状态管理 | ⚠️ 需要手动处理 | ✅ 完善的状态回调 |
| HarmonyOS 支持 | ❌ 无 | ✅ 完善适配 |
核心功能
| 功能 | 说明 | HarmonyOS 支持 |
|---|---|---|
| date 日期模式 | 选择年月日 | ✅ |
| time 时间模式 | 选择时分秒 | ✅ |
| datetime 日期时间模式 | 同时选择日期和时间 | ⚠️ 仅模态框模式支持 |
| 模态框展示 | 弹窗式选择器 | ✅ |
| 内嵌展示 | 页面内直接展示 | ⚠️ datetime 模式不支持 |
| 最大/最小日期 | 日期范围限制 | ✅ |
| 分钟间隔 | 分钟选择粒度 | ❌ |
兼容性验证
在以下环境验证通过:
- RNOH: 0.72.90; SDK: HarmonyOS 6.0.0 ; IDE: DevEco Studio 6.0.01; ROM: 6.0.0
📦 安装步骤
1. 安装依赖
请到三方库的 Releases 发布地址查看配套的版本信息:@react-native-ohos/react-native-date-picker Releases
# RN 0.72 版本
npm install @react-native-ohos/react-native-date-picker@5.0.6-rc.1
# 或者使用 yarn
yarn add @react-native-ohos/react-native-date-picker@5.0.6-rc.1
2. 验证安装
安装完成后,检查 package.json 文件:
{
"dependencies": {
"@react-native-ohos/react-native-date-picker": "^5.0.6-rc.1"
}
}
🔧 HarmonyOS 平台配置 ⭐
本库支持 AutoLink(RN 0.72 的 5.0.6 版本及以上,RN 0.77 版本),如果您的工程已接入 AutoLink,可跳过手动配置。否则请按以下步骤配置。
1. 在工程根目录的 oh-package.json5 添加 overrides 字段

打开 harmony/oh-package.json5,添加以下配置:
{
// ... 其他配置
"overrides": {
"@rnoh/react-native-openharmony": "0.72.90"
}
}
方式一:AutoLink
如果您的工程已接入 AutoLink,只需安装依赖即可,无需手动配置。
验证 AutoLink 是否生效
安装依赖后,执行以下命令同步:
cd harmony/entry
ohpm install
然后编译运行即可。
方式二:HAR 包引入(手动配置,用这个)
2.1 在 entry/oh-package.json5 添加依赖
打开 harmony/entry/oh-package.json5,添加以下依赖:
"dependencies": {
"@react-native-ohos/react-native-date-picker": "file:../../node_modules/@react-native-ohos/react-native-date-picker/harmony/date_picker.har"
}
2.2 同步依赖
点击 DevEco Studio 右上角的 sync 按钮,或者在终端执行:
cd harmony/entry
ohpm install
2.3 配置 CMakeLists.txt
打开 harmony/entry/src/main/cpp/CMakeLists.txt,添加以下配置:
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(NODE_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../node_modules")
+ set(OH_MODULE "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_CPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../react-native-harmony/harmony/cpp")
set(LOG_VERBOSITY_LEVEL 1)
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
set(WITH_HITRACE_SYSTRACE 1)
add_compile_definitions(WITH_HITRACE_SYSTRACE)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
# 添加 DatePicker 模块
+ add_subdirectory("${OH_MODULE}/@react-native-ohos/react-native-date-picker/src/main/cpp" ./date_picker)
file(GLOB GENERATED_CPP_FILES "./generated/*.cpp")
add_library(rnoh_app SHARED
${GENERATED_CPP_FILES}
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
# 链接 DatePicker 库
+ target_link_libraries(rnoh_app PUBLIC rnoh_date_picker)
2.4 修改 PackageProvider.cpp
打开 harmony/entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "DatePickerPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
+ std::make_shared<DatePickerPackage>(ctx),
};
}
2.5 在 ArkTs 侧引入 RNDatePicker 组件
找到 entry/src/main/ets/pages/index.ets 或 entry/src/main/ets/rn/LoadBundle.ets,在 buildCustomRNComponent 函数中添加:
+ import { RNDatePicker } from "@react-native-ohos/react-native-date-picker"
@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {
// ... 其他组件
if (ctx.componentName === RNDatePicker.NAME) {
RNDatePicker({
ctx: ctx.rnComponentContext,
tag: ctx.tag
})
}
// ...
}
2.6 添加组件名到 arkTsComponentNames
在相同文件中找到 arkTsComponentNames 数组,添加组件名:
const arkTsComponentNames: Array<string> = [
// ... 其他组件名
RNDatePicker.NAME,
];
2.7 在 ArkTs 侧引入 RNDatePickerPackage
打开 entry/src/main/ets/RNPackagesFactory.ts,添加:
import { RNDatePickerPackage } from "@react-native-ohos/react-native-date-picker/ts";
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
// ... 其他包
new RNDatePickerPackage(ctx)
];
}
同步并运行 🚀
点击 DevEco Studio 右上角的 sync 按钮,或者在终端执行:
cd harmony/entry
ohpm install
然后编译、运行即可。
📖 API 详解
DatePicker Props
基础属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
mode |
“date”| “time” | “datetime” | ✅ | 选择器模式 | ✅ |
date |
Date | ❌ | 当前选中的日期 | ✅ |
onDateChange |
function | ❌ | 日期变化回调(仅内联模式)(date: Date) => void |
✅ |
maximumDate |
Date | ❌ | 最大可选日期 | ✅ |
minimumDate |
Date | ❌ | 最小可选日期 | ✅ |
模态框属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
modal |
boolean | ❌ | 是否启用模态框模式,默认 false | ✅ |
open |
boolean | ❌ | 控制模态框是否打开 | ✅ |
onConfirm |
function | ❌ | 确认按钮回调 (date: Date) => void |
✅ |
onCancel |
function | ❌ | 取消按钮回调 () => void |
✅ |
样式属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
title |
string | ❌ | 模态框标题(设为 null 可隐藏) | ❌ |
confirmText |
string | ❌ | 确认按钮文本 | ❌ |
cancelText |
string | ❌ | 取消按钮文本 | ❌ |
theme |
“light”| “dark” | “auto” | ❌ | 模态框主题 | ❌ |
buttonColor |
string | ❌ | 按钮颜色(仅 Android) | ❌ |
dividerColor |
string | ❌ | 分隔线颜色(仅 Android) | ❌ |
其他属性
| 属性 | 类型 | 必填 | 说明 | HarmonyOS 支持 |
|---|---|---|---|---|
locale |
string | ❌ | 区域设置(如 “zh-CN”) | ❌ |
is24hourSource |
“locale”| “device” | ❌ | 24小时制来源 | ❌ |
minuteInterval |
1| 2 | 3 | 4 | 5 | 6 | 10 | 12 | 15 | 20 | 30 | ❌ | 分钟间隔 | ❌ |
timeZoneOffsetInMinutes |
number | ❌ | 时区偏移量 | ❌ |
📋 完整示例

综合示例(日期/时间/日期时间/预约场景)
import React, { useState } from 'react';
import {
View,
Text,
Button,
StyleSheet,
TouchableOpacity,
ScrollView,
Alert,
} from 'react-native';
import DatePicker from 'react-native-date-picker';
type PickerMode = 'date' | 'time' | 'datetime';
interface PickerConfig {
mode: PickerMode;
title: string;
minDate?: Date;
maxDate?: Date;
}
const App: React.FC = () => {
const [date, setDate] = useState(new Date());
const [pickerOpen, setPickerOpen] = useState(false);
const [pickerConfig, setPickerConfig] = useState<PickerConfig>({
mode: 'date',
title: '选择日期',
});
const openPicker = (mode: PickerMode, title: string, min?: Date, max?: Date) => {
setPickerConfig({ mode, title, minDate: min, maxDate: max });
setPickerOpen(true);
};
const handleConfirm = (selectedDate: Date) => {
setDate(selectedDate);
setPickerOpen(false);
};
const handleCancel = () => {
setPickerOpen(false);
};
const formatDate = (d: Date): string => {
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
};
const formatTime = (d: Date): string => {
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
};
const formatDateTime = (d: Date): string => {
return `${formatDate(d)} ${formatTime(d)}`;
};
const calculateAge = (birthDate: Date): number => {
const today = new Date();
let age = today.getFullYear() - birthDate.getFullYear();
const monthDiff = today.getMonth() - birthDate.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
return age;
};
const getDayName = (d: Date): string => {
const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
return days[d.getDay()];
};
return (
<ScrollView style={styles.container}>
<Text style={styles.header}>react-native-date-picker 示例</Text>
{/* 当前选中值展示 */}
<View style={styles.currentValue}>
<Text style={styles.currentLabel}>当前选中的值:</Text>
<Text style={styles.currentDate}>{formatDate(date)}</Text>
<Text style={styles.currentTime}>{formatTime(date)}</Text>
<Text style={styles.currentWeekday}>{getDayName(date)}</Text>
</View>
{/* 基础模式选择 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>基础模式</Text>
<View style={styles.buttonRow}>
<Button
title="日期选择"
onPress={() => openPicker('date', '选择日期', new Date(2020, 0, 1), new Date(2030, 11, 31))}
/>
<Button
title="时间选择"
onPress={() => openPicker('time', '选择时间')}
/>
<Button
title="日期时间"
onPress={() => openPicker('datetime', '选择日期时间', new Date())}
/>
</View>
</View>
{/* 生日选择示例 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>生日选择</Text>
<TouchableOpacity
style={styles.birthdayCard}
onPress={() => openPicker('date', '选择生日', new Date(1900, 0, 1), new Date())}
>
<View style={styles.birthdayContent}>
<Text style={styles.birthdayLabel}>您的生日</Text>
<Text style={styles.birthdayDate}>
{date.getFullYear()}年{date.getMonth() + 1}月{date.getDate()}日
</Text>
<Text style={styles.ageText}>年龄: {calculateAge(date)} 岁</Text>
</View>
<Text style={styles.editHint}>点击修改 ✎</Text>
</TouchableOpacity>
</View>
{/* 预约场景示例 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>服务预约</Text>
<View style={styles.bookingCard}>
<Text style={styles.bookingLabel}>选择预约时间</Text>
<TouchableOpacity
style={styles.dateButton}
onPress={() => openPicker('datetime', '选择预约时间', new Date())}
>
<Text style={styles.dateButtonText}>{formatDateTime(date)}</Text>
<Text style={styles.dayText}>{getDayName(date)}</Text>
</TouchableOpacity>
<Button
title="立即预约"
onPress={() => Alert.alert(`预约成功!\\n预约时间: ${formatDateTime(date)}`)}
/>
</View>
</View>
{/* DatePicker - 使用内置模态框 */}
<DatePicker
modal
mode={pickerConfig.mode}
open={pickerOpen}
date={date}
onConfirm={handleConfirm}
onCancel={handleCancel}
minimumDate={pickerConfig.minDate}
maximumDate={pickerConfig.maxDate}
/>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#F5F5F5',
},
header: {
fontSize: 24,
fontWeight: 'bold',
color: '#333',
textAlign: 'center',
marginBottom: 30,
},
currentValue: {
backgroundColor: '#FFF',
borderRadius: 12,
padding: 20,
alignItems: 'center',
marginBottom: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
currentLabel: {
fontSize: 14,
color: '#999',
marginBottom: 8,
},
currentDate: {
fontSize: 28,
fontWeight: 'bold',
color: '#333',
},
currentTime: {
fontSize: 18,
color: '#666',
marginTop: 4,
},
currentWeekday: {
fontSize: 14,
color: '#007AFF',
marginTop: 4,
},
section: {
marginBottom: 24,
},
sectionTitle: {
fontSize: 16,
fontWeight: '600',
color: '#333',
marginBottom: 12,
},
buttonRow: {
flexDirection: 'row',
justifyContent: 'space-between',
gap: 10,
},
birthdayCard: {
backgroundColor: '#FFF',
borderRadius: 12,
padding: 20,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
birthdayContent: {
flex: 1,
},
birthdayLabel: {
fontSize: 14,
color: '#999',
marginBottom: 4,
},
birthdayDate: {
fontSize: 20,
fontWeight: 'bold',
color: '#333',
marginBottom: 4,
},
ageText: {
fontSize: 14,
color: '#666',
},
editHint: {
fontSize: 14,
color: '#007AFF',
},
bookingCard: {
backgroundColor: '#FFF',
borderRadius: 12,
padding: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
elevation: 3,
},
bookingLabel: {
fontSize: 14,
color: '#999',
marginBottom: 12,
},
dateButton: {
backgroundColor: '#F5F5F5',
borderRadius: 8,
padding: 16,
marginBottom: 16,
},
dateButtonText: {
fontSize: 18,
fontWeight: '600',
color: '#333',
},
dayText: {
fontSize: 14,
color: '#666',
marginTop: 4,
},
});
export default App;
⚠️ 约束与限制
暂不支持的功能
| 功能 | 说明 | 相关 Issue |
|---|---|---|
confirmText |
确认按钮文本自定义 | issue#11 |
cancelText |
取消按钮文本自定义 | issue#12 |
theme |
模态框主题设置 | issue#13 |
locale |
区域语言设置 | issue#17 |
timeZoneOffsetInMinutes |
时区偏移设置 | issue#18 |
is24hourSource |
24小时制来源设置 | issue#30 |
minuteInterval |
分钟间隔设置 | issue#34 |
已知问题
- 内联 datetime 模式不支持:当
modal为false,mode为datetime时,HarmonyOS 不支持内联 datetime 组件。请使用模态框模式。 - 日期回弹动画:由于本库封装了 ArkUI DatePicker 组件,滑出设置范围的日期需要等待拖尾动画结束后才会回弹,这是预期行为。
建议
- 使用模态框模式:建议使用
modal={true}配合open属性控制日期选择器的展示 - datetime 模式必须使用模态框:内联模式不支持 datetime,请务必配合
modal={true}使用 - 日期范围限制:使用
minimumDate和maximumDate限制可选日期范围,提升用户体验
📚 更多资源
- 官方文档: https://github.com/henninghall/react-native-date-picker
- HarmonyOS 适配库: https://github.com/react-native-oh-library/react-native-date-picker
- 问题反馈: https://github.com/react-native-oh-library/react-native-date-picker/issues
更多推荐



所有评论(0)