一、核心知识点:长度换算器 完整核心用法

1. 用到的纯内置组件与 API

所有能力均为 RN 原生自带,零基础易理解、易复用,无任何额外依赖:

核心组件 / API 作用说明
TextInput 数值输入框,用于获取用户输入的长度值,支持键盘类型限制(数字键盘)
Text 文本展示,用于显示单位名称、换算结果、提示文字
View 布局容器,组织页面结构,实现输入框与结果的排版
TouchableOpacity 可点击按钮,用于实现 “一键清空” 功能
useState React 状态钩子,管理三个单位的数值状态,实现实时更新
StyleSheet 样式管理,编写鸿蒙端适配的页面样式,避免样式错乱

二、双向实时换算 + 一键清空 + 输入校验

import React, { useState } from 'react';
import { View, Text, TextInput, StyleSheet, SafeAreaView, TouchableOpacity } from 'react-native';

const filterNumber = (text: string): string => {
  return text.replace(/[^0-9.]/g, '').replace(/(\..*)\./g, '$1');
};

const LengthConverterBusiness = () => {
  const [meter, setMeter] = useState<string>('');
  const [cm, setCm] = useState<string>('');
  const [mm, setMm] = useState<string>('');

  const handleMeterChange = (text: string) => {
    const filtered = filterNumber(text);
    setMeter(filtered);
    if (!filtered) {
      setCm('');
      setMm('');
      return;
    }
    const num = parseFloat(filtered);
    setCm((num * 100).toString());
    setMm((num * 1000).toString());
  };

  const handleCmChange = (text: string) => {
    const filtered = filterNumber(text);
    setCm(filtered);
    if (!filtered) {
      setMeter('');
      setMm('');
      return;
    }
    const num = parseFloat(filtered);
    setMeter((num / 100).toString());
    setMm((num * 10).toString());
  };

  const handleMmChange = (text: string) => {
    const filtered = filterNumber(text);
    setMm(filtered);
    if (!filtered) {
      setMeter('');
      setCm('');
      return;
    }
    const num = parseFloat(filtered);
    setMeter((num / 1000).toString());
    setCm((num / 10).toString());
  };

  // 一键清空所有输入框
  const handleClearAll = () => {
    setMeter('');
    setCm('');
    setMm('');
  };

  return (
    <SafeAreaView style={styles.container}>
      <Text style={styles.title}>通用长度换算器</Text>
      <Text style={styles.subTitle}>米(m) / 厘米(cm) / 毫米(mm)</Text>

      <View style={styles.inputGroup}>
        {/* 米输入框 */}
        <View style={styles.inputItem}>
          <TextInput
            style={styles.input}
            placeholder="请输入米数"
            keyboardType="numeric"
            value={meter}
            onChangeText={handleMeterChange}
            placeholderTextColor="#999"
          />
          <Text style={styles.unit}>米(m)</Text>
        </View>

        {/* 厘米输入框 */}
        <View style={styles.inputItem}>
          <TextInput
            style={styles.input}
            placeholder="请输入厘米数"
            keyboardType="numeric"
            value={cm}
            onChangeText={handleCmChange}
            placeholderTextColor="#999"
          />
          <Text style={styles.unit}>厘米(cm)</Text>
        </View>

        {/* 毫米输入框 */}
        <View style={styles.inputItem}>
          <TextInput
            style={styles.input}
            placeholder="请输入毫米数"
            keyboardType="numeric"
            value={mm}
            onChangeText={handleMmChange}
            placeholderTextColor="#999"
          />
          <Text style={styles.unit}>毫米(mm)</Text>
        </View>
      </View>

      {/* 清空按钮 */}
      <TouchableOpacity style={styles.clearBtn} onPress={handleClearAll}>
        <Text style={styles.clearBtnText}>一键清空</Text>
      </TouchableOpacity>
    </SafeAreaView>
  );
};

// 鸿蒙端业务样式(贴合鸿蒙设计规范)
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#f7f8fa',
  },
  title: {
    fontSize: 22,
    color: '#333',
    textAlign: 'center',
    marginBottom: 8,
    fontWeight: '600',
  },
  subTitle: {
    fontSize: 14,
    color: '#666',
    textAlign: 'center',
    marginBottom: 30,
  },
  inputGroup: {
    gap: 15,
    marginBottom: 25,
  },
  inputItem: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#fff',
    borderRadius: 12,
    paddingHorizontal: 18,
    height: 52,
    borderWidth: 1,
    borderColor: '#e5e5e5',
  },
  input: {
    flex: 1,
    fontSize: 16,
    color: '#333',
  },
  unit: {
    fontSize: 16,
    color: '#666',
    marginLeft: 10,
  },
  clearBtn: {
    backgroundColor: '#007DFF',
    borderRadius: 12,
    height: 52,
    justifyContent: 'center',
    alignItems: 'center',
  },
  clearBtnText: {
    fontSize: 16,
    color: '#fff',
    fontWeight: '500',
  },
});

export default LengthConverterBusiness;

三、OpenHarmony6.0 专属避坑指南

以下是鸿蒙 RN 开发中实现长度换算器的真实高频踩坑点,解决方案简单直接,全部真机实测验证通过,彻底规避功能异常和样式错乱:

问题现象 问题原因 鸿蒙端解决方案
输入框可输入字母 / 符号,导致换算结果为 NaN 未限制输入类型,也未做输入过滤 ✅ 1. 设置 keyboardType="numeric" 调出数字键盘;2. 用正则过滤非数字字符(参考 filterNumber 工具函数)
输入小数点后,出现多个小数点(如 12..3) 未处理重复小数点的输入 ✅ 正则过滤:replace(/(\..*)\./g, '$1'),确保输入框中只有一个小数点
换算结果出现超长小数(如 0.3333333333) 未限制小数位数,影响展示效果 ✅ 使用 toFixed(n) 限制小数位数,如 (num * 100).toFixed(2) 保留 2 位小数
鸿蒙端输入框点击后,键盘弹出遮挡按钮 未处理键盘弹出的布局适配 ✅ 在根组件外层包裹 KeyboardAvoidingView,自动调整布局避免遮挡
清空按钮点击无反应 按钮未绑定 onPress 事件,或 TouchableOpacity 样式设置错误 ✅ 确保绑定 onPress={handleClearAll},按钮设置固定高度,避免因高度为 0 导致无法点击
TypeScript 报错 parseFloat 参数类型不匹配 直接将 string 类型的输入值传给 parseFloat,未处理空字符串 ✅ 先判断输入值非空,再执行 parseFloat,避免传入空字符串导致 NaN

四、扩展用法:长度换算器 功能升级技巧

基于本次的基础版本,可轻松扩展更多实用功能,适配更复杂的业务场景,全部为纯内置 API 实现:

1. 增加更多长度单位

添加分米 (dm)、千米 (km) 等单位,只需扩展换算公式和输入框状态,例如:

// 千米与米的换算:1km = 1000m
const handleKmChange = (text: string) => {
  const filtered = filterNumber(text);
  setKm(filtered);
  if (!filtered) { setMeter(''); return; }
  setMeter((parseFloat(filtered) * 1000).toString());
};

2. 限制小数位数

通过 toFixed(n) 限制换算结果的小数位数,避免超长小数,提升用户体验:

// 保留2位小数
setCm((num * 100).toFixed(2));

3. 增加换算历史记录

使用 useState 管理历史记录数组,每次换算时保存结果,实现历史记录的展示和清空:

const [history, setHistory] = useState<string[]>([]);
// 换算时添加记录
const addHistory = (m: string, c: string, mm: string) => {
  setHistory([`${m}m = ${c}cm = ${mm}mm`, ...history]);
};

4. 持久化存储历史记录

结合 AsyncStorage 将历史记录保存到本地,APP 重启后依然保留,实现数据持久化:

// 保存记录
await AsyncStorage.setItem('length_history', JSON.stringify(history));
// 读取记录
const savedHistory = await AsyncStorage.getItem('length_history');
if (savedHistory) setHistory(JSON.parse(savedHistory));

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐