当前位置: 首页 > news >正文

ReactNative【实战系列教程】我的小红书 2 -- 快捷登录、手机号密码登录

最终效果

在这里插入图片描述

在这里插入图片描述

技术要点

用户协议 – 打开本地浏览器

点击后,直接打开本地浏览器浏览网页

 // 最终需修改为 《用户协议》 的网址Linking.openURL("https://www.baidu.com");

手机号输入框的 344 展示

在这里插入图片描述

onChangeText={(text: string) => {setPhone(formatPhone(text));
}}
export function formatPhone(phone: string): string {let trim: string = phone.replace(/\s+/g, "");const result = [trim.slice(0, 3), trim.slice(3, 7), trim.slice(7, 11)].filter((item) => !!item).join(" ");return result;
}

但在访问接口登录时,传参需清除空格

UserStore.requestLogin(replaceBlank(phone), pwd, (success: boolean) => {
export function replaceBlank(phone: string): string {return phone ? phone.replace(/\s+/g, "") : "";
}

代码实现

app/_layout.tsx

        <Stack>{/* 登录页 */}<Stack.Screen name="login" options={{ headerShown: false }} /><Stack.Screen name="(tabs)" options={{ headerShown: false }} /><Stack.Screen name="+not-found" /></Stack>

app/login.tsx

import UserStore from "@/stores/UserStore";
import { formatPhone, replaceBlank } from "@/utils/StringUtil";
import { Toast } from "@ant-design/react-native";
import AntDesign from "@expo/vector-icons/AntDesign";
import Entypo from "@expo/vector-icons/Entypo";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import { useRouter } from "expo-router";
import { useState } from "react";
import {Image,KeyboardAvoidingView,Linking,Platform,StyleSheet,Text,TextInput,TouchableOpacity,View,
} from "react-native";
import Animated from "react-native-reanimated";
export default function LoginScreen() {const router = useRouter();const [ifRead, setIfRead] = useState(false);const [ifQuickLogin, setIfQuickLogin] = useState(false);const [phone, setPhone] = useState<string>("");const [pwd, setPwd] = useState<string>("");const [showPassword, setShowPassword] = useState(false);const canLogin = phone?.length === 13 && pwd?.length >= 6;const onLoginPress = async () => {if (!canLogin) {return;}if (!ifRead) {Toast.show({content: "请先同意并阅读用户协议",});return;}UserStore.requestLogin(replaceBlank(phone), pwd, (success: boolean) => {if (success) {Toast.success("登录成功");router.replace("/(tabs)");} else {Toast.fail("登录失败,账号/密码错误!");}});};const render_passwordLogin = () => {const passwordLogin_styles = StyleSheet.create({inputBox: {borderColor: "#ccc",borderBottomColor: "#ccc",borderBottomWidth: 1,flexDirection: "row",alignItems: "center",marginBottom: 14,height: 55,},phonePrefix: {fontSize: 20,color: "#bbb",marginRight: 8,},phoneInput: {fontSize: 24,paddingLeft: 14,textAlignVertical: "bottom",height: 75,flex: 1,},passwordInput: {fontSize: 20,textAlignVertical: "bottom",flex: 1,height: 75,},loginButton: {backgroundColor: "#ff2442",},loginButtonDisable: {backgroundColor: "#DDDDDD",},moreBox: {flexDirection: "row",justifyContent: "space-between",marginBottom: 26,},tip: {fontSize: 14,color: "#bbb",marginBottom: 20,textAlign: "center",},toCodeLoginBtn: {flexDirection: "row",alignItems: "center",},toCodeLoginBtnTxt: {marginLeft: 6,},moreBoxTxt: {color: "#303080",},});return (<View><Text style={passwordLogin_styles.tip}>未注册的手机号登录成功后将自动注册</Text><KeyboardAvoidingViewbehavior={Platform.OS === "ios" ? "padding" : "height"}keyboardVerticalOffset={Platform.OS === "ios" ? 64 : 30}><View style={passwordLogin_styles.inputBox}><Text style={passwordLogin_styles.phonePrefix}>+86</Text><AntDesign name="caretdown" size={14} color="#bbb" /><TextInputstyle={passwordLogin_styles.phoneInput}placeholder="请输入手机号"placeholderTextColor="#bbb"autoFocus={false}keyboardType="number-pad"maxLength={13}value={phone}onChangeText={(text: string) => {setPhone(formatPhone(text));}}/></View><View style={passwordLogin_styles.inputBox}><TextInputstyle={passwordLogin_styles.passwordInput}placeholder="请输入密码"placeholderTextColor="#bbb"autoFocus={false}maxLength={20}secureTextEntry={!showPassword}value={pwd}onChangeText={(text: string) => {setPwd(text);}}/><TouchableOpacityactiveOpacity={0.7}onPress={() => {setShowPassword(!showPassword);}}><Entyponame={showPassword ? "eye" : "eye-with-line"}size={28}color="#bbb"/></TouchableOpacity></View></KeyboardAvoidingView><View style={passwordLogin_styles.moreBox}><TouchableOpacitystyle={passwordLogin_styles.toCodeLoginBtn}onPress={() => {Toast.show({content: "待需要时完善",});}}><FontAwesome name="exchange" size={12} color="#303080" /><Textstyle={[passwordLogin_styles.toCodeLoginBtnTxt,passwordLogin_styles.moreBoxTxt,]}>验证码登录</Text></TouchableOpacity><TouchableOpacityonPress={() => {Toast.show({content: "待需要时完善",});}}><Text style={passwordLogin_styles.moreBoxTxt}>忘记密码?</Text></TouchableOpacity></View><TouchableOpacitystyle={[styles.btn,canLogin? passwordLogin_styles.loginButton: passwordLogin_styles.loginButtonDisable,]}activeOpacity={canLogin ? 0.7 : 1}onPress={onLoginPress}><Text style={[styles.btnTxt]}>登录</Text></TouchableOpacity></View>);};return (<View style={styles.page}><Imagesource={require("@/assets/images/icon.png")}style={{ width: 200, height: 200, marginTop: 100 }}resizeMode="cover"/><Animated.View style={styles.LoginBox}>{ifQuickLogin ? (<><TouchableOpacitystyle={[styles.btn, styles.oneKeyLoginButton]}activeOpacity={0.7}onPress={() => {Toast.show({content: "待需要时完善",});}}><Text style={[styles.btnTxt, styles.oneKeyLoginTxt]}>一键登录</Text></TouchableOpacity><TouchableOpacitystyle={[styles.btn, styles.wxLoginButton]}activeOpacity={0.7}onPress={() => {Toast.show({content: "待需要时完善",});}}><AntDesign name="wechat" size={24} color="white" /><Text style={[styles.btnTxt]}>微信登录</Text></TouchableOpacity></>) : (render_passwordLogin())}<TouchableOpacityactiveOpacity={0.7}style={styles.moreLoginWayBox}onPress={() => {setIfQuickLogin(!ifQuickLogin);}}><Text style={[styles.moreLoginWayTxt]}>{ifQuickLogin ? "其他登录方式" : "快捷登录"}</Text><Entypo name="chevron-small-right" size={20} /></TouchableOpacity><View style={styles.moreBox}><TouchableOpacityonPress={() => {setIfRead(!ifRead);}}>{ifRead ? (<AntDesignstyle={styles.moreIcon}name="checkcircle"size={14}color="#05c160"/>) : (<Entypostyle={styles.moreIcon}name="circle"size={14}color="gray"/>)}</TouchableOpacity><Text style={styles.infoTxt}>我已阅读并同意</Text><TouchableOpacityonPress={() => {// 最终需修改为 《用户协议》 的网址Linking.openURL("https://www.baidu.com");}}><Text style={styles.linkTxt}>《用户协议》</Text></TouchableOpacity><Text style={styles.infoTxt}></Text><TouchableOpacityonPress={() => {// 最终需修改为 《隐私政策》 的网址Linking.openURL("https://www.baidu.com");}}><Text style={styles.linkTxt}>《隐私政策》</Text></TouchableOpacity></View></Animated.View></View>);
}
const styles = StyleSheet.create({page: {flex: 1,alignItems: "center",justifyContent: "space-between",backgroundColor: "#e8e8e7",padding: 40,},LoginBox: {width: "100%",padding: 20,marginBottom: 100,},btn: {width: "100%",height: 56,borderRadius: 28,justifyContent: "center",alignItems: "center",flexDirection: "row",marginBottom: 20,},btnTxt: {fontSize: 18,color: "white",marginBottom: 6,marginLeft: 14,},oneKeyLoginButton: {backgroundColor: "#ff2442",},oneKeyLoginTxt: {marginLeft: 4,},wxLoginButton: {backgroundColor: "#05c160",},moreBox: {flexDirection: "row",alignItems: "center",justifyContent: "center",},moreIcon: {marginRight: 4,marginTop: 2,},moreLoginWayBox: {flexDirection: "row",alignItems: "center",justifyContent: "center",marginBottom: 60,},moreLoginWayTxt: {fontSize: 16,marginBottom: 4,},infoTxt: {fontSize: 14,color: "gray",},linkTxt: {fontSize: 14,color: "blue",},
});

utils/StringUtil.ts

export function formatPhone(phone: string): string {let trim: string = phone.replace(/\s+/g, "");const result = [trim.slice(0, 3), trim.slice(3, 7), trim.slice(7, 11)].filter((item) => !!item).join(" ");return result;
}
export function replaceBlank(phone: string): string {return phone ? phone.replace(/\s+/g, "") : "";
}
http://www.lqws.cn/news/557479.html

相关文章:

  • 一站式了解SPI机制
  • NVIDIA 开源高性能语音识别模型:Parakeet TDT 0.6B V2 登顶 OpenASR 榜单
  • 【算法深练】单调栈:有序入栈,及时删除垃圾数据
  • 代理与反射
  • 基于LQR控制器的六自由度四旋翼无人机模型simulink建模与仿真
  • 微软人工智能证书AI-102 | 如何快速通过?
  • 桌面小屏幕实战课程:DesktopScreen 16 HTTP
  • 【软考--软件设计师】11 关系型数据库
  • WebRTC(十二):DTLS
  • 关于前端页面上传图片检测
  • 暑假复习篇之运算与逻辑
  • UI前端大数据可视化创新:利用AR/VR技术提升用户沉浸感
  • 什么是集中刷新,分散刷新,和异步刷新
  • 从 AJAX 到 axios:前端与服务器通信实战指南
  • 2023国赛linux的应急响应-wp
  • Re--攻防世界-基础android
  • C++ vector 完全指南:从入门到精通
  • 源码运行效果图(六)
  • 【HarmonyOS Next之旅】DevEco Studio使用指南(三十八) -> 构建HAR
  • 基于springboot的海产品交易系统
  • 【数据标注师】3D标注
  • JWT认证性能优化实战指南
  • 《从 0 到 1 掌握正则表达式:解析串口数据的万能钥匙》
  • springboot+Vue逍遥大药房管理系统
  • 创建套接字时和填充地址时指定类型的异同
  • C++泛型编程2 - 类模板
  • 【数论】P11169 「CMOI R1」Bismuth / Linear Sieve|普及+
  • 嵌入式硬件与应用篇---寄存器GPIO控制
  • 进阶向:Flask框架详解,从零开始理解Web开发利器
  • Odoo邮箱别名使用指南:从配置到业务流程自动化