react-native-calendarsReact Native库来帮助你处理日期和时间,实现鸿蒙跨平台开发日历组件 - 指南

在React Native中开发一个保养日程表功能,你可以按照以下步骤进行:

  1. 初始化项目

如果你还没有创建一个React Native项目,你可以使用以下命令来初始化一个新的项目:

npx react-native init CarMaintenanceSchedule
cd CarMaintenanceSchedule
  1. 安装依赖

你可能需要一些额外的库来帮助你处理日期和时间,例如react-native-calendars。使用npm或yarn来安装这些库:

npm install react-native-calendars

或者使用yarn:

yarn add react-native-calendars
  1. 创建日历组件

使用react-native-calendars库来创建一个日历组件,用户可以在上面选择日期。

import React from 'react';
import { Calendar } from 'react-native-calendars';
import { View } from 'react-native';
const CalendarComponent = () => {
return (
<View>
  <Calendar
  onDayPress={day => {
  console.log('selected day', day);
  }}
  markedDates={{
  '2023-04-12': { selected: true, selectedColor: 'blue' }, // Custom marking
  }}
  />
  </View>
    );
    };
    export default CalendarComponent;
  1. 添加保养事项输入功能

你可以使用TextInputButton来让用户输入特定的保养事项和选择日期。

import React, { useState } from 'react';
import { View, TextInput, Button, Text, Alert } from 'react-native';
import CalendarComponent from './CalendarComponent'; // 假设你已经创建了CalendarComponent组件文件
const MaintenanceForm = () => {
const [task, setTask] = useState('');
const [date, setDate] = useState('');
const [tasks, setTasks] = useState([]); // 存储所有任务和日期
const handleSubmit = () => {
if (task && date) {
setTasks([...tasks, { task, date }]); // 添加到任务列表中
Alert.alert('Task Added', 'Task has been added successfully.');
setTask(''); // 清空输入框内容
setDate(''); // 清空日期选择内容(如果需要的话,你可能需要更复杂的逻辑来处理日期)
} else {
Alert.alert('Error', 'Please enter both task and date.');
}
};
return (
<View>
  <TextInput
  placeholder="Enter maintenance task"
  value={task}
  onChangeText={setTask}
  />
  <TextInput
  placeholder="Select date"
  value={date}
  onChangeText={setDate}
  editable={false} // 如果使用外部日历组件选择日期,则可以设置为不可编辑,并通过日历组件的回调设置此值。如果直接在TextInput选择,则需要额外的日期选择器库或自定义实现。例如使用react-native-datepicker。
  />
  <Button title="Add Task" onPress={handleSubmit} />
    <Text>Scheduled Tasks:</Text>
      {tasks.map((item, index) => (
      <Text key={index}>{item.date}: {item.task}</Text> // 显示所有任务和日期信息。根据实际需求调整显示格式。例如,你可能需要格式化日期。可以使用moment.js等库。
        ))}
        </View>
          );
          };

注意:在上面的代码中,TextInput用于选择日期是不可编辑的,因为通常我们会使用一个外部的日历组件来选择日期。如果你想要在TextInput中选择日期,你可以使用react-native-datepicker或者类似的库。例如:

npm install react-native-datepicker --save // 或者 yarn add react-native-datepicker

然后在代码中使用它:

import DatePicker from 'react-native-datepicker'; // 引入DatePicker组件。确保链接了相应的库(例如Harmony的权限)。具体可以查看react-native-datepicker的文档进行配置。例如:https://github.com/xgfe/react-native-datepickerHarmony--Harmony--windows--web-support。通常Harmony需要配置权限和一些额外的链接步骤。对于Harmony,通常只需要安装库并导入即可。对于Windows和Web平台,也需要确保正确配置。具体配置方法请参考官方

真实项目组件案例演示:

// app.tsx
import React, { useState } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ScrollView, Image, Alert } from 'react-native';
const App = () => {
const [currentMonth, setCurrentMonth] = useState(new Date());
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
  const [events, setEvents] = useState<Record<string, any[]>>({
    '2023-10-15': [
    { id: 1, title: '机油更换', time: '09:00', vehicle: '丰田凯美瑞' }
    ],
    '2023-10-22': [
    { id: 2, title: '轮胎保养', time: '14:30', vehicle: '本田雅阁' }
    ],
    '2023-10-28': [
    { id: 3, title: '刹车系统检查', time: '10:00', vehicle: '大众帕萨特' },
    { id: 4, title: '空调滤芯更换', time: '15:00', vehicle: '日产轩逸' }
    ]
    });
    // Base64 icons
    const icons = {
    prev: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cG9seWxpbmUgcG9pbnRzPSIxNSAxOCA5IDEyIDE1IDYiPjwvcG9seWxpbmU+PC9zdmc+',
    next: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cG9seWxpbmUgcG9pbnRzPSI5IDYgMTUgMTIgOSAxOCI+PC9wb2x5bGluZT48L3N2Zz4=',
    calendar: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48cmVjdCB4PSIzIiB5PSI0IiB3aWR0aD0iMTgiIGhlaWdodD0iMTgiIHJ4PSIyIiByeT0iMiI+PC9yZWN0PjxsaW5lIHgxPSI4IiB5MT0iMiIgeDI9IjgiIHkyPSI2Ij48L2xpbmU+PGxpbmUgeDE9IjE2IiB5MT0iMiIgeDI9IjE2IiB5Mj0iNiI+PC9saW5lPjxsaW5lIHgxPSIzIiB5MT0iMTAiIHgyPSIyMSIgeTI9IjEwIj48L2xpbmU+PC9zdmc+',
    event: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCI+PC9jaXJjbGU+PHBvbHlsaW5lIHBvaW50cz0iMTIgNiAxMiAxMiAxNiAxNCI+PC9wb2x5bGluZT48L3N2Zz4=',
    add: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiM0Mjg1RjQiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIj48Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCI+PC9jaXJjbGU+PGxpbmUgeDE9IjEyIiB5MT0iOCIgeDI9IjEyIiB5Mj0iMTYiPjwvbGluZT48bGluZSB4MT0iOCIgeTE9IjEyIiB4Mj0iMTYiIHkyPSIxMiI+PC9saW5lPjwvc3ZnPg=='
    };
    // 获取月份的天数
    const getDaysInMonth = (date: Date) => {
    const year = date.getFullYear();
    const month = date.getMonth();
    const firstDay = new Date(year, month, 1);
    const lastDay = new Date(year, month + 1, 0);
    const daysInMonth = lastDay.getDate();
    const startingDayOfWeek = firstDay.getDay();
    const days = [];
    // 添加上个月的日期
    const prevMonthLastDay = new Date(year, month, 0).getDate();
    for (let i = startingDayOfWeek - 1; i >= 0; i--) {
    days.push({
    day: prevMonthLastDay - i,
    isCurrentMonth: false,
    date: new Date(year, month - 1, prevMonthLastDay - i)
    });
    }
    // 添加当前月的日期
    for (let i = 1; i <= daysInMonth; i++) {
    days.push({
    day: i,
    isCurrentMonth: true,
    date: new Date(year, month, i)
    });
    }
    // 添加下个月的日期
    const totalCells = 42; // 6行7列
    const remainingCells = totalCells - days.length;
    for (let i = 1; i <= remainingCells; i++) {
    days.push({
    day: i,
    isCurrentMonth: false,
    date: new Date(year, month + 1, i)
    });
    }
    return days;
    };
    // 格式化日期为 YYYY-MM-DD
    const formatDate = (date: Date) => {
    return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;
    };
    // 切换月份
    const changeMonth = (direction: number) => {
    setCurrentMonth(prev => {
    const newMonth = new Date(prev);
    newMonth.setMonth(prev.getMonth() + direction);
    return newMonth;
    });
    };
    // 检查日期是否有事件
    const hasEvents = (date: Date) => {
    const dateStr = formatDate(date);
    return events[dateStr] && events[dateStr].length > 0;
    };
    // 获取星期标题
    const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
    // 当前月份的天数数组
    const days = getDaysInMonth(currentMonth);
    return (
    <ScrollView style={styles.container}>
      <View style={styles.header}>
        <Text style={styles.title}>保养日程表</Text>
          <Text style={styles.subtitle}>管理您的车辆保养计划</Text>
            </View>
              {/* 日历头部 */}
              <View style={styles.calendarHeader}>
                <TouchableOpacity onPress={() => changeMonth(-1)} style={styles.navButton}>
                  <Image source={{ uri: icons.prev }} style={styles.navIcon} />
                    </TouchableOpacity>
                      <View style={styles.monthYearContainer}>
                        <Text style={styles.monthYearText}>
                          {currentMonth.getFullYear()}{currentMonth.getMonth() + 1}</Text>
                            </View>
                              <TouchableOpacity onPress={() => changeMonth(1)} style={styles.navButton}>
                                <Image source={{ uri: icons.next }} style={styles.navIcon} />
                                  </TouchableOpacity>
                                    </View>
                                      {/* 星期标题 */}
                                      <View style={styles.weekdaysContainer}>
                                        {weekdays.map((day, index) => (
                                        <View key={index} style={styles.weekdayCell}>
                                          <Text style={[
                                          styles.weekdayText,
                                          index === 0 && styles.sundayText,
                                          index === 6 && styles.saturdayText
                                          ]}>
                                          {day}
                                          </Text>
                                            </View>
                                              ))}
                                              </View>
                                                {/* 日历主体 */}
                                                <View style={styles.calendarGrid}>
                                                  {days.map((dayObj, index) => {
                                                  const isSelected = selectedDate &&
                                                  selectedDate.getDate() === dayObj.day &&
                                                  selectedDate.getMonth() === dayObj.date.getMonth() &&
                                                  selectedDate.getFullYear() === dayObj.date.getFullYear();
                                                  const hasEvent = hasEvents(dayObj.date);
                                                  return (
                                                  <TouchableOpacity
                                                  key={index}
                                                  style={[
                                                  styles.dayCell,
                                                  !dayObj.isCurrentMonth && styles.otherMonthDay,
                                                  isSelected && styles.selectedDay
                                                  ]}
                                                  onPress={() => setSelectedDate(dayObj.date)}
                                                  >
                                                  <View style={styles.dayContent}>
                                                    <Text style={[
                                                    styles.dayText,
                                                    !dayObj.isCurrentMonth && styles.otherMonthDayText,
                                                    isSelected && styles.selectedDayText
                                                    ]}>
                                                    {dayObj.day}
                                                    </Text>
                                                      {hasEvent && (
                                                      <View style={styles.eventIndicator}>
                                                        <Image source={{ uri: icons.event }} style={styles.eventIcon} />
                                                          </View>
                                                            )}
                                                            </View>
                                                              </TouchableOpacity>
                                                                );
                                                                })}
                                                                </View>
                                                                  {/* 事件详情 */}
                                                                  <View style={styles.eventsContainer}>
                                                                    <View style={styles.eventsHeader}>
                                                                      <Text style={styles.eventsTitle}>
                                                                        {selectedDate
                                                                        ? `${selectedDate.getMonth() + 1}${selectedDate.getDate()}日的保养安排`
                                                                        : '请选择日期查看保养安排'}
                                                                        </Text>
                                                                          <TouchableOpacity style={styles.addButton}>
                                                                            <Image source={{ uri: icons.add }} style={styles.addIcon} />
                                                                              <Text style={styles.addButtonText}>添加</Text>
                                                                                </TouchableOpacity>
                                                                                  </View>
                                                                                    {selectedDate ? (
                                                                                    <View style={styles.eventsList}>
                                                                                      {events[formatDate(selectedDate)] ? (
                                                                                      events[formatDate(selectedDate)].map(event => (
                                                                                      <View key={event.id} style={styles.eventCard}>
                                                                                        <View style={styles.eventHeader}>
                                                                                          <Text style={styles.eventTitle}>{event.title}</Text>
                                                                                            <Text style={styles.eventTime}>{event.time}</Text>
                                                                                              </View>
                                                                                                <Text style={styles.eventVehicle}>{event.vehicle}</Text>
                                                                                                  </View>
                                                                                                    ))
                                                                                                    ) : (
                                                                                                    <View style={styles.emptyEvents}>
                                                                                                      <Text style={styles.emptyEventsText}>当天没有保养安排</Text>
                                                                                                        </View>
                                                                                                          )}
                                                                                                          </View>
                                                                                                            ) : (
                                                                                                            <View style={styles.emptyEvents}>
                                                                                                              <Text style={styles.emptyEventsText}>请选择一个日期查看保养安排</Text>
                                                                                                                </View>
                                                                                                                  )}
                                                                                                                  </View>
                                                                                                                    </ScrollView>
                                                                                                                      );
                                                                                                                      };
                                                                                                                      const styles = StyleSheet.create({
                                                                                                                      container: {
                                                                                                                      flex: 1,
                                                                                                                      backgroundColor: '#f8f9fa',
                                                                                                                      padding: 20
                                                                                                                      },
                                                                                                                      header: {
                                                                                                                      alignItems: 'center',
                                                                                                                      marginBottom: 25,
                                                                                                                      paddingTop: 20
                                                                                                                      },
                                                                                                                      title: {
                                                                                                                      fontSize: 26,
                                                                                                                      fontWeight: 'bold',
                                                                                                                      color: '#2c3e50'
                                                                                                                      },
                                                                                                                      subtitle: {
                                                                                                                      fontSize: 15,
                                                                                                                      color: '#7f8c8d',
                                                                                                                      marginTop: 6
                                                                                                                      },
                                                                                                                      calendarHeader: {
                                                                                                                      flexDirection: 'row',
                                                                                                                      alignItems: 'center',
                                                                                                                      justifyContent: 'space-between',
                                                                                                                      marginBottom: 20,
                                                                                                                      backgroundColor: '#fff',
                                                                                                                      borderRadius: 16,
                                                                                                                      padding: 15,
                                                                                                                      elevation: 3,
                                                                                                                      shadowColor: '#000',
                                                                                                                      shadowOffset: { width: 0, height: 2 },
                                                                                                                      shadowOpacity: 0.1,
                                                                                                                      shadowRadius: 4
                                                                                                                      },
                                                                                                                      navButton: {
                                                                                                                      padding: 10
                                                                                                                      },
                                                                                                                      navIcon: {
                                                                                                                      width: 24,
                                                                                                                      height: 24
                                                                                                                      },
                                                                                                                      monthYearContainer: {
                                                                                                                      alignItems: 'center'
                                                                                                                      },
                                                                                                                      monthYearText: {
                                                                                                                      fontSize: 20,
                                                                                                                      fontWeight: 'bold',
                                                                                                                      color: '#2c3e50'
                                                                                                                      },
                                                                                                                      weekdaysContainer: {
                                                                                                                      flexDirection: 'row',
                                                                                                                      backgroundColor: '#4285F4',
                                                                                                                      borderRadius: 12,
                                                                                                                      overflow: 'hidden',
                                                                                                                      marginBottom: 10
                                                                                                                      },
                                                                                                                      weekdayCell: {
                                                                                                                      flex: 1,
                                                                                                                      alignItems: 'center',
                                                                                                                      paddingVertical: 12
                                                                                                                      },
                                                                                                                      weekdayText: {
                                                                                                                      fontSize: 16,
                                                                                                                      fontWeight: '600',
                                                                                                                      color: '#fff'
                                                                                                                      },
                                                                                                                      sundayText: {
                                                                                                                      color: '#ffebee'
                                                                                                                      },
                                                                                                                      saturdayText: {
                                                                                                                      color: '#e3f2fd'
                                                                                                                      },
                                                                                                                      calendarGrid: {
                                                                                                                      flexDirection: 'row',
                                                                                                                      flexWrap: 'wrap',
                                                                                                                      backgroundColor: '#fff',
                                                                                                                      borderRadius: 16,
                                                                                                                      overflow: 'hidden',
                                                                                                                      elevation: 3,
                                                                                                                      shadowColor: '#000',
                                                                                                                      shadowOffset: { width: 0, height: 2 },
                                                                                                                      shadowOpacity: 0.1,
                                                                                                                      shadowRadius: 4,
                                                                                                                      marginBottom: 25
                                                                                                                      },
                                                                                                                      dayCell: {
                                                                                                                      width: '14.28%',
                                                                                                                      aspectRatio: 1,
                                                                                                                      alignItems: 'center',
                                                                                                                      justifyContent: 'center',
                                                                                                                      borderBottomWidth: 1,
                                                                                                                      borderRightWidth: 1,
                                                                                                                      borderColor: '#eee'
                                                                                                                      },
                                                                                                                      otherMonthDay: {
                                                                                                                      backgroundColor: '#f8f9fa'
                                                                                                                      },
                                                                                                                      selectedDay: {
                                                                                                                      backgroundColor: '#4285F4'
                                                                                                                      },
                                                                                                                      dayContent: {
                                                                                                                      alignItems: 'center'
                                                                                                                      },
                                                                                                                      dayText: {
                                                                                                                      fontSize: 18,
                                                                                                                      fontWeight: '500',
                                                                                                                      color: '#34495e'
                                                                                                                      },
                                                                                                                      otherMonthDayText: {
                                                                                                                      color: '#bdc3c7'
                                                                                                                      },
                                                                                                                      selectedDayText: {
                                                                                                                      color: '#fff'
                                                                                                                      },
                                                                                                                      eventIndicator: {
                                                                                                                      position: 'absolute',
                                                                                                                      bottom: 2,
                                                                                                                      right: 2
                                                                                                                      },
                                                                                                                      eventIcon: {
                                                                                                                      width: 10,
                                                                                                                      height: 10
                                                                                                                      },
                                                                                                                      eventsContainer: {
                                                                                                                      backgroundColor: '#fff',
                                                                                                                      borderRadius: 16,
                                                                                                                      padding: 20,
                                                                                                                      elevation: 3,
                                                                                                                      shadowColor: '#000',
                                                                                                                      shadowOffset: { width: 0, height: 2 },
                                                                                                                      shadowOpacity: 0.1,
                                                                                                                      shadowRadius: 4
                                                                                                                      },
                                                                                                                      eventsHeader: {
                                                                                                                      flexDirection: 'row',
                                                                                                                      justifyContent: 'space-between',
                                                                                                                      alignItems: 'center',
                                                                                                                      marginBottom: 20
                                                                                                                      },
                                                                                                                      eventsTitle: {
                                                                                                                      fontSize: 20,
                                                                                                                      fontWeight: 'bold',
                                                                                                                      color: '#2c3e50',
                                                                                                                      flex: 1
                                                                                                                      },
                                                                                                                      addButton: {
                                                                                                                      flexDirection: 'row',
                                                                                                                      alignItems: 'center',
                                                                                                                      backgroundColor: '#4285F4',
                                                                                                                      borderRadius: 20,
                                                                                                                      paddingHorizontal: 15,
                                                                                                                      paddingVertical: 8
                                                                                                                      },
                                                                                                                      addIcon: {
                                                                                                                      width: 18,
                                                                                                                      height: 18,
                                                                                                                      marginRight: 6
                                                                                                                      },
                                                                                                                      addButtonText: {
                                                                                                                      color: '#fff',
                                                                                                                      fontWeight: '600',
                                                                                                                      fontSize: 15
                                                                                                                      },
                                                                                                                      eventsList: {
                                                                                                                      gap: 15
                                                                                                                      },
                                                                                                                      eventCard: {
                                                                                                                      backgroundColor: '#f8f9fa',
                                                                                                                      borderRadius: 12,
                                                                                                                      padding: 16,
                                                                                                                      borderWidth: 1,
                                                                                                                      borderColor: '#eef2f7'
                                                                                                                      },
                                                                                                                      eventHeader: {
                                                                                                                      flexDirection: 'row',
                                                                                                                      justifyContent: 'space-between',
                                                                                                                      marginBottom: 8
                                                                                                                      },
                                                                                                                      eventTitle: {
                                                                                                                      fontSize: 18,
                                                                                                                      fontWeight: 'bold',
                                                                                                                      color: '#2c3e50'
                                                                                                                      },
                                                                                                                      eventTime: {
                                                                                                                      fontSize: 16,
                                                                                                                      color: '#4285F4',
                                                                                                                      fontWeight: '600'
                                                                                                                      },
                                                                                                                      eventVehicle: {
                                                                                                                      fontSize: 15,
                                                                                                                      color: '#7f8c8d'
                                                                                                                      },
                                                                                                                      emptyEvents: {
                                                                                                                      paddingVertical: 30,
                                                                                                                      alignItems: 'center'
                                                                                                                      },
                                                                                                                      emptyEventsText: {
                                                                                                                      fontSize: 16,
                                                                                                                      color: '#95a5a6',
                                                                                                                      fontStyle: 'italic'
                                                                                                                      }
                                                                                                                      });
                                                                                                                      export default App;

这段React Native代码实现了一个功能完整的车辆保养日历组件,其核心原理基于React的状态管理和日期处理机制。getDaysInMonth函数通过日期运算计算当前月份的天数,通过创建上个月和下个月的日期填充日历网格,确保日历始终显示完整的6行7列布局。这种日期计算方式在鸿蒙系统的日历组件中具有重要意义,鸿蒙设备的屏幕尺寸和布局要求使得这种动态填充机制能够自适应不同设备的显示需求。

从鸿蒙系统适配的角度来看,该代码充分利用了React Native的跨平台特性,在鸿蒙设备上能够获得原生级的性能表现。鸿蒙系统的分布式数据管理能力能够与React的状态提升概念良好结合,events状态作为单一数据源确保了数据一致性。日期选择功能通过selectedDate状态管理当前选中日期,通过条件渲染实现不同日期的样式变化,这种交互设计符合鸿蒙系统的UI规范。

日历导航功能通过changeMonth函数实现月份切换,通过setMonth方法更新currentMonth状态,这种状态管理方式在鸿蒙系统的应用生命周期管理中非常重要,能够确保组件在不同使用场景下的状态一致性。日期格式化函数formatDate通过padStart方法确保日期字符串的格式统一性,这种数据处理方式在鸿蒙系统的数据同步机制中具有实际价值。

请添加图片描述

UI布局采用ScrollView作为根容器,确保内容在不同屏幕尺寸设备上的可滚动性。日历头部通过TouchableOpacity组件实现月份切换按钮,通过条件渲染显示当前月份和年份,这种交互设计符合鸿蒙系统的用户界面规范。星期标题区域通过map方法遍历weekdays数组生成7个标签,通过条件渲染实现周末标签的特殊样式,这种信息架构在鸿蒙系统的健康数据展示中非常常见。

日历主体区域通过map方法遍历days数组生成42个日期单元格,每个单元格根据isCurrentMonth状态应用不同样式,通过hasEvents函数检查日期是否有事件并显示指示器图标。这种条件渲染模式在鸿蒙系统的动态UI构建中具有优势,能够根据数据变化实时更新界面。日期选择功能通过onPress回调函数更新selectedDate状态,通过条件渲染实现选中日期的高亮显示,这种交互设计符合鸿蒙系统的UI规范。

事件详情区域通过条件渲染显示选中日期的保养安排,通过map方法遍历events数组生成事件列表。这种信息架构在鸿蒙系统的健康数据展示中非常常见,能够帮助用户快速获取关键信息。事件指示器图标通过Image组件加载远程图片资源,这种远程图片加载方式在鸿蒙系统的网络图片缓存机制中能够获得良好的性能表现。

从鸿蒙系统的技术特性来看,该代码通过React Native的声明式编程范式,将复杂的日期逻辑抽象为简单的状态转换。鸿蒙系统的ArkUI框架同样强调声明式UI开发,这种设计思想的一致性使得应用在鸿蒙设备上能够获得接近原生的性能表现。组件的生命周期管理与鸿蒙系统的应用管理机制保持一致,能够在应用前后台切换时正确处理状态更新。


打包

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

在这里插入图片描述

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

在这里插入图片描述

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

请添加图片描述

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

posted @ 2026-01-15 22:18  yangykaifa  阅读(0)  评论(0)    收藏  举报