Skip to content

个人主页/小工具APP - 表单提交

表单提交功能实现

在本节中,我们将为个人主页/小工具APP添加表单提交功能。我们将创建一个用户个人资料编辑页面,允许用户修改个人信息并提交表单。

步骤1:创建个人资料编辑页面

创建 src/screens/ProfileEditScreen.js 文件:

javascript
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView, Alert } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';

const ProfileEditScreen = () => {
  const navigation = useNavigation();
  const route = useRoute();
  
  // 从路由参数中获取当前用户信息
  const initialData = route.params?.userData || {
    name: '张三',
    email: 'zhangsan@example.com',
    phone: '13800138000',
    bio: '这是个人简介',
  };
  
  // 表单状态
  const [formData, setFormData] = useState(initialData);
  const [errors, setErrors] = useState({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  
  // 处理输入变化
  const handleChange = (name, value) => {
    setFormData(prev => ({
      ...prev,
      [name]: value
    }));
    
    // 清除错误
    if (errors[name]) {
      setErrors(prev => {
        const newErrors = { ...prev };
        delete newErrors[name];
        return newErrors;
      });
    }
  };
  
  // 表单验证
  const validateForm = () => {
    const newErrors = {};
    
    if (!formData.name.trim()) {
      newErrors.name = '请输入姓名';
    }
    
    if (!formData.email.trim()) {
      newErrors.email = '请输入邮箱';
    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
      newErrors.email = '请输入有效的邮箱地址';
    }
    
    if (!formData.phone.trim()) {
      newErrors.phone = '请输入手机号';
    } else if (!/^1[3-9]\d{9}$/.test(formData.phone)) {
      newErrors.phone = '请输入有效的手机号';
    }
    
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  // 处理表单提交
  const handleSubmit = async () => {
    if (!validateForm()) {
      return;
    }
    
    setIsSubmitting(true);
    
    try {
      // 模拟API请求
      await new Promise(resolve => setTimeout(resolve, 1000));
      
      // 提交成功
      Alert.alert('成功', '个人信息已更新', [
        {
          text: '确定',
          onPress: () => {
            // 返回上一页并传递更新后的数据
            navigation.goBack();
          }
        }
      ]);
    } catch (error) {
      Alert.alert('错误', '提交失败,请稍后重试');
    } finally {
      setIsSubmitting(false);
    }
  };
  
  return (
    <ScrollView style={styles.container}>
      <View style={styles.form}>
        <Text style={styles.title}>编辑个人资料</Text>
        
        <View style={styles.inputContainer}>
          <Text style={styles.label}>姓名</Text>
          <TextInput
            style={[styles.input, errors.name && styles.inputError]}
            value={formData.name}
            onChangeText={(text) => handleChange('name', text)}
            placeholder="请输入姓名"
          />
          {errors.name && <Text style={styles.errorText}>{errors.name}</Text>}
        </View>
        
        <View style={styles.inputContainer}>
          <Text style={styles.label}>邮箱</Text>
          <TextInput
            style={[styles.input, errors.email && styles.inputError]}
            value={formData.email}
            onChangeText={(text) => handleChange('email', text)}
            placeholder="请输入邮箱"
            keyboardType="email-address"
            autoCapitalize="none"
          />
          {errors.email && <Text style={styles.errorText}>{errors.email}</Text>}
        </View>
        
        <View style={styles.inputContainer}>
          <Text style={styles.label}>手机号</Text>
          <TextInput
            style={[styles.input, errors.phone && styles.inputError]}
            value={formData.phone}
            onChangeText={(text) => handleChange('phone', text)}
            placeholder="请输入手机号"
            keyboardType="phone-pad"
          />
          {errors.phone && <Text style={styles.errorText}>{errors.phone}</Text>}
        </View>
        
        <View style={styles.inputContainer}>
          <Text style={styles.label}>个人简介</Text>
          <TextInput
            style={[styles.input, styles.textArea]}
            value={formData.bio}
            onChangeText={(text) => handleChange('bio', text)}
            placeholder="请输入个人简介"
            multiline
            numberOfLines={4}
          />
        </View>
        
        <TouchableOpacity
          style={[styles.button, isSubmitting && styles.buttonDisabled]}
          onPress={handleSubmit}
          disabled={isSubmitting}
        >
          <Text style={styles.buttonText}>
            {isSubmitting ? '提交中...' : '保存修改'}
          </Text>
        </TouchableOpacity>
      </View>
    </ScrollView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  form: {
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
    textAlign: 'center',
  },
  inputContainer: {
    marginBottom: 16,
  },
  label: {
    fontSize: 16,
    marginBottom: 8,
    fontWeight: '500',
  },
  input: {
    backgroundColor: '#fff',
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    padding: 12,
    fontSize: 16,
  },
  textArea: {
    height: 100,
    textAlignVertical: 'top',
  },
  inputError: {
    borderColor: '#ff3b30',
  },
  errorText: {
    color: '#ff3b30',
    fontSize: 12,
    marginTop: 4,
  },
  button: {
    backgroundColor: '#007AFF',
    borderRadius: 8,
    padding: 16,
    alignItems: 'center',
    marginTop: 20,
  },
  buttonDisabled: {
    backgroundColor: '#ccc',
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

export default ProfileEditScreen;

步骤2:更新导航配置

更新 src/navigation/StackNavigators.js 文件,添加个人资料编辑页面:

javascript
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from '../screens/HomeScreen';
import ProfileScreen from '../screens/ProfileScreen';
import ProfileEditScreen from '../screens/ProfileEditScreen';
import CalculatorScreen from '../screens/tools/CalculatorScreen';
import NotesScreen from '../screens/tools/NotesScreen';
import NoteDetailScreen from '../screens/tools/NoteDetailScreen';

const Stack = createStackNavigator();

export const HomeStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen 
        name="HomeMain" 
        component={HomeScreen} 
        options={{ title: '首页' }}
      />
    </Stack.Navigator>
  );
};

export const ProfileStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen 
        name="ProfileMain" 
        component={ProfileScreen} 
        options={{ title: '个人中心' }}
      />
      <Stack.Screen 
        name="ProfileEdit" 
        component={ProfileEditScreen} 
        options={{ title: '编辑资料' }}
      />
    </Stack.Navigator>
  );
};

export const ToolsStack = () => {
  return (
    <Stack.Navigator>
      <Stack.Screen 
        name="ToolsMain" 
        component={ToolsScreen} 
        options={{ title: '工具' }}
      />
      <Stack.Screen 
        name="Calculator" 
        component={CalculatorScreen} 
        options={{ title: '计算器' }}
      />
      <Stack.Screen 
        name="Notes" 
        component={NotesScreen} 
        options={{ title: '便签' }}
      />
      <Stack.Screen 
        name="NoteDetail" 
        component={NoteDetailScreen} 
        options={{ title: '便签详情' }}
      />
    </Stack.Navigator>
  );
};

步骤3:更新个人中心页面

更新 src/screens/ProfileScreen.js 文件,添加编辑资料按钮:

javascript
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native';
import { useNavigation } from '@react-navigation/native';

const ProfileScreen = () => {
  const navigation = useNavigation();
  
  // 模拟用户数据
  const userData = {
    name: '张三',
    email: 'zhangsan@example.com',
    phone: '13800138000',
    bio: '这是个人简介',
  };
  
  const handleEditProfile = () => {
    navigation.navigate('ProfileEdit', { userData });
  };
  
  return (
    <View style={styles.container}>
      <View style={styles.header}>
        <Image 
          source={{ uri: 'https://via.placeholder.com/150' }} 
          style={styles.avatar}
        />
        <Text style={styles.name}>{userData.name}</Text>
        <Text style={styles.email}>{userData.email}</Text>
        
        <TouchableOpacity 
          style={styles.editButton}
          onPress={handleEditProfile}
        >
          <Text style={styles.editButtonText}>编辑资料</Text>
        </TouchableOpacity>
      </View>
      
      <View style={styles.infoSection}>
        <Text style={styles.infoTitle}>个人信息</Text>
        <View style={styles.infoItem}>
          <Text style={styles.infoLabel}>手机号:</Text>
          <Text style={styles.infoValue}>{userData.phone}</Text>
        </View>
        <View style={styles.infoItem}>
          <Text style={styles.infoLabel}>简介:</Text>
          <Text style={styles.infoValue}>{userData.bio}</Text>
        </View>
      </View>
      
      <View style={styles.menuSection}>
        <TouchableOpacity style={styles.menuItem}>
          <Text style={styles.menuText}>设置</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.menuItem}>
          <Text style={styles.menuText}>关于</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.menuItem}>
          <Text style={styles.menuText}>退出登录</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  header: {
    backgroundColor: '#fff',
    padding: 20,
    alignItems: 'center',
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
  },
  avatar: {
    width: 100,
    height: 100,
    borderRadius: 50,
    marginBottom: 16,
  },
  name: {
    fontSize: 20,
    fontWeight: 'bold',
    marginBottom: 8,
  },
  email: {
    fontSize: 14,
    color: '#666',
    marginBottom: 16,
  },
  editButton: {
    backgroundColor: '#007AFF',
    paddingHorizontal: 20,
    paddingVertical: 8,
    borderRadius: 20,
  },
  editButtonText: {
    color: '#fff',
    fontSize: 14,
    fontWeight: '500',
  },
  infoSection: {
    backgroundColor: '#fff',
    marginTop: 16,
    padding: 20,
  },
  infoTitle: {
    fontSize: 16,
    fontWeight: '600',
    marginBottom: 16,
  },
  infoItem: {
    flexDirection: 'row',
    marginBottom: 12,
  },
  infoLabel: {
    fontSize: 14,
    color: '#666',
    width: 80,
  },
  infoValue: {
    fontSize: 14,
    flex: 1,
  },
  menuSection: {
    backgroundColor: '#fff',
    marginTop: 16,
  },
  menuItem: {
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
  },
  menuText: {
    fontSize: 16,
  },
});

export default ProfileScreen;

步骤4:更新工具页面导入

确保 src/navigation/StackNavigators.js 中导入了 ToolsScreen

javascript
import ToolsScreen from '../screens/ToolsScreen';

表单提交功能总结

在本部分中,我们实现了以下功能:

  1. 个人资料编辑页面:创建了一个包含姓名、邮箱、手机号和个人简介的表单
  2. 表单验证:实现了基本的表单验证逻辑,包括必填项和格式验证
  3. 表单提交:模拟了表单提交过程,包括加载状态和错误处理
  4. 导航集成:将编辑页面集成到导航系统中,支持页面间数据传递
  5. 用户界面:设计了美观的表单界面,包括输入框、标签和错误提示

下一步

在下一节中,我们将继续完善个人主页/小工具APP,添加原生功能整合,包括相机/相册调用、定位功能等。

© 2026 编程马·菜鸟教程 版权所有