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.pswp.cn/bicheng/87080.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/87080.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/87080.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【趙渝強老師】OceanBase數據庫從零開始:Oracle模式

這里我們來介紹一下新上線的課程《OceanBase數據庫從零開始&#xff1a;Oracle模式》&#xff0c;本門課程共11章。 視頻講解如下 【趙渝強老師】OceanBase從零開始&#xff08;Oracle模式&#xff09; 下面詳細介紹一下每一章的主要內容&#xff1a; 第01章-OceanBase的體系…

Flink核心功能與運行流程詳解

目錄 一、背景 二、圖構建 三、任務執行流程&#xff08;yarn per-job模式&#xff09; 3.1 Flink組件 3.2 執行流程 四、分布式調度 4.1 TM的slot 4.2 TM的slot的CPU與內存 4.3 節點的部署 4.4 節點的狀態 4.5 節點部署流程 五、數據傳輸 5.1 內存分配 5.2 傳輸…

linux 操作docker的基本命令docker倉庫

基本操作命令 docker run --nametest-host -itd centos7.6 /bin/bash 通過鏡像創建容器 登錄容器 [rootdocker101 ~]# docker exec -it test-host /bin/bash &#xff08;exec是執行&#xff0c;i是交互式。t叫tty&#xff09; 或者container id [rootdocker101 ~]# doc…

Netty學習路線圖 - 第四階段:Netty基礎應用

Netty學習路線圖 - 第四階段&#xff1a;Netty基礎應用 &#x1f4da; Netty學習系列之四 本文是Netty學習路線的第四篇&#xff0c;我們將用大白話講解Netty的基礎應用&#xff0c;帶你從理論走向實踐。 寫在前面 大家好&#xff01;在前面三篇文章中&#xff0c;我們學習了J…

開源項目推薦:MCP Registry——管理MCP服務器的利器

探索MCP Registry:未來模型上下文協議的核心注冊服務 隨著人工智能技術的迅速發展,機器學習模型的管理和配置變得愈發重要。今天,我們將探索一個頗具潛力的開源項目——MCP Registry。這是一個由社區驅動的注冊服務,專為模型上下文協議(Model Context Protocol,簡稱MCP)…

Spring Boot 統一功能處理:攔截器詳解

一、攔截器核心概念 作用&#xff1a;攔截器是 Spring 框架提供的核心功能&#xff0c;用于在請求處理前后執行預定義邏輯&#xff0c;實現統一處理&#xff08;如登錄校驗、日志記錄等&#xff09;。 核心方法&#xff1a; public class LoginInterceptor implements Handl…

在docker容器中安裝docker服務,基于fuse-overlayfs進行overlay掛載,而不是vfs

1、docker 安裝 正常安裝docker軟件&#xff0c;運行docker時&#xff0c;會提示&#xff1a;No docker socket 服務 2、啟動docker服務&#xff08;包含守護進程&#xff09; systemctl start docker #dockerd &if ! ps aux | grep -v grep | grep -q "dockerd&qu…

虛擬機配置注意事項

一.VM大部分產品免費&#xff0c;遇到付費的要斟酌一下 在小編之前的文章中有簡單下載VM的教程VMwareWorkstPro安裝-CSDN博客 二.配置過程中的設置大部分都可以在配置完成后更改 例如下圖設備所涉及到的&#xff0c;都是可以更改設置的 三.電腦關機時&#xff0c;要注意先把…

openGL+QT快速學習和入門案列

openGLQT快速學習和入門案列

深度學習03 人工神經網絡ANN

什么是神經網絡 人工神經網絡&#xff08; Artificial Neural Network&#xff0c; 簡寫為ANN&#xff09;也簡稱為神經網絡&#xff08;NN&#xff09;,是一種模仿生物神經網絡結構和功能的計算模型,人腦可以看做是一個生物神經網絡,由眾多的神經元連接而成.各個神經元傳遞復…

Linux中部署Jenkins保姆間教程

本文將以docker的方式&#xff0c;講述如何部署Jenkins 一、拉取Jenkins鏡像 1.1 最新版Jenkins介紹 最新版Jenkins地址&#xff1a;Download and deploy 當前最新版的如下圖所示&#xff1a; 1.2 各版本支持的JDK版本 地址如下&#xff1a;Java Support Policy 如果你安裝…

【軟考中級·軟件評測師】下午題·面向對象測試之架構考點全析:分層、分布式、微內核與事件驅動

一、分層架構&#xff1a;分層獨立與質量特性的雙向約束 分層架構通過“垂直分層&#xff08;表示層→服務層→業務邏輯層→數據層&#xff09;”實現職責隔離&#xff0c;是Web應用、企業級系統的主流架構模式。 1. 父類成員函數重測場景 子類繼承父類時&#xff0c;若父類…

C++ 快速回顧(五)

C 快速回顧&#xff08;五&#xff09; 前言一、Dll和Lib的區別區別在開發中使用 二、封裝并使用C庫1.封裝庫2.使用庫 三、封裝并使用C庫1.封裝庫2.使用庫 前言 用于快速回顧之前遺漏或者補充C知識 一、Dll和Lib的區別 靜態庫&#xff08;LIB&#xff09;在編譯時鏈接&#…

【ARM】解決ArmDS的工程沒有生成Map文件的問題

1、 文檔目標 在嵌入式開發過程中&#xff0c;使用Arm Development Studio&#xff08;簡稱ArmDS&#xff09;進行項目構建時&#xff0c;Map文件的生成是調試和分析代碼的重要環節。Map文件不僅記錄了程序中各個段&#xff08;sections&#xff09;的內存分布情況&#xff0c…

Java如何導出word(根據模板生成),通過word轉成pdf,放壓縮包

<!-- 導出word文檔所需依賴--><dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.10.0-beta</version></dependency><dependency><groupId>org.apache.poi</gr…

【C#】 DevExpress.XtraEditors.SidePanel

DevExpress.XtraEditors.SidePanel&#xff0c; 它是 DevExpress 提供的“側邊滑出”面板&#xff08;類似于抽屜、浮動信息區&#xff09;&#xff0c;非常適合做可隱藏的參數區、幫助區、臨時交互區等。 SidePanel 用法核心點 1. 基本用法 可容納其它控件&#xff0c;就像普…

1.1_2 計算機網絡的組成和功能

在這個視頻中&#xff0c;我們會探討計算機網絡的組成和功能。我們會從三個視角去探討計算機網絡由哪些部分組成&#xff0c;其次&#xff0c;我們會簡單的了解計算機網絡的功能。 首先我們可以把計算機網絡看作是由硬件、軟件和協議共同組成的一個龐大復雜的系統。首先在硬件上…

Linux驅動學習day11(定時器)

定時器 定時器主要作用就是&#xff1a;設置超時時間&#xff0c;執行超時函數。 按鍵按下存在抖動&#xff0c;為了消除抖動可以設置定時器&#xff0c;如上圖所示&#xff0c;按下一次按鍵會產生多次抖動&#xff0c;即會產生多次中斷&#xff0c;在每次中斷產生的時候&…

Java 編程之觀察者模式詳解

一、什么是觀察者模式&#xff1f; 觀察者模式&#xff08;Observer Pattern&#xff09;是一種行為型設計模式&#xff0c;用于對象之間的一對多依賴關系&#xff1a;當被觀察對象&#xff08;Subject&#xff09;狀態發生變化時&#xff0c;所有依賴它的觀察者&#xff08;O…

【C++】經典string類問題

目錄 1. 淺拷貝 2. 深拷貝 3. string類傳統寫法 4. string類現代版寫法 5. 自定義類實現swap成員函數 6. 標準庫swap函數的調用 7. 引用計數和寫時拷貝 1. 淺拷貝 若string類沒有顯示定義拷貝構造函數與賦值運算符重載&#xff0c;編譯器會自動生成默認的&#xff0c…