HarmonyOS Next 实现登录注册页面(ARKTS) 并使用Springboot作为后端提供接口
1. HarmonyOS next
ArkTS
ArkTS围绕应用开发在 TypeScript (简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集
ArkTS在TS的基础上扩展了struct和很多的装饰器以达到描述UI和状态管理的目的
以下代码是一个基于 HarmonyOS 的登录页面组件的示例代码,主要实现了用户登录功能以及一些数据存储和页面跳转的操作。下面我会逐步解释每个部分并添加注释:
2. 实例

3. 功能分区
1.1.HTTP获取后台接口数据,以下是示例
async jwt(jwt: string) {try {const res = await this.httpUtil.request(`192.168.xxx.xxx/readers/userinfo`, {method: http.RequestMethod.GET,extraData: { no: jwt },});let data = JSON.parse(res.result.toString());return data;} catch (error) {throw error;}}
1.2 接口数据(作为测试,可以直接使用json):

2.生命周期函数的使用–AboutToAppear AboutToDisappear
aboutToAppear() {let httpRequest = http.createHttp()this.httpUtil = httpRequest// todo 初始化上一次访问时间this.getPreTime()// todo 初始化当前时间this.getLocalTimeToPreference()// todo 初始化本地数据库的密码和用户名this.getUserInfo()}
3.APPStorage进程作为缓存,只能在应用运行时使用
4.DATAPreference 数据持久化,存于用户本机
4. 分层结构

4.代码演示
1. 导入模块:
import router from '@ohos.router' // 导入路由模块
import storage from '@ohos.data.storage' // 导入数据存储模块
import App from '@system.app' // 导入应用模块
import Prompt from '@system.prompt' // 导入提示模块
import http from '@ohos.net.http' // 导入网络请求模块
import { RouterInfo } from '../../Pojo/RouterInfo' // 导入自定义的 RouterInfo 类
import common from '@ohos.app.ability.common' // 导入通用模块
import dataPreference from '@ohos.data.preferences' // 导入数据首选项模块
2. 定义 `Login` 结构体:
@Entry
@Component
struct Login {
? // 定义状态变量
? @State username: string = ""
? @State pwd: string = ""
? @State allow: boolean = false
? @State upload: boolean = true
? @State uploadTag: boolean = false
? @State lastLocalTime: string = ""
??
? // 其他属性和方法...
}
3. 实例化 `RouterInfo` 对象和初始化方法:
RouterInfo是一个自定义的类
export class RouterInfo{name:stringurl:stringmessage:stringconstructor(name,url,message) {this.name=namethis.url=urlthis.message=message}
}Router = new RouterInfo("进入主页", "pages/Books/Main", "主页面")aboutToAppear() {
? // 初始化操作,包括创建 HTTP 请求对象、获取上次访问时间、初始化本地时间等
}
4. 页面跳转方法 `goTo()`:
goTo(Router: RouterInfo) {
? // 调用路由模块进行页面跳转
}
5. 异步获取用户信息的方法 `jwt()`:
async jwt(jwt: string) {
? // 发起网络请求获取用户信息
}
6. 存储当前时间到用户首选项方法 `getLocalTimeToPreference()`:
// 获取当前时间并存入用户首选项getLocalTimeToPreference(){const currentDate: Date = new Date();const currentYear: number = currentDate.getFullYear();const currentMonth: number = currentDate.getMonth() + 1; // 注意:月份从 0 开始,需要加 1const currentDay: number = currentDate.getDate();const currentHour: number = currentDate.getHours();const currentMinute: number = currentDate.getMinutes();const currentSecond: number = currentDate.getSeconds();const curTime = `北京时间:${currentYear}-${currentMonth}-${currentDay} ${currentHour}:${currentMinute}:${currentSecond}`;dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {preferences.put("curTime", curTime).then(_ => {preferences.flush();});}).catch((err: Error) => {console.error(err.message);});}
7. 获取上一次访问时间方法 `getPreTime()` 和关闭应用更新时间方法
// 获取上一次的时间--lastTimegetPreTime(){dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {if (!preferences.has("lastTime")) {console.log("数据并未能保存");} else {preferences.get("lastTime", 'null').then((value) => {this.last=value.toLocaleString()// AlertDialog.show({message:`上一次访问时间:${this.last}`})console.log("数据为:" + value);}).catch(_ => {console.log("读取失败");});}});}// 关闭应用时将lastTime置换为curTime,并将curTime替换为空值closeAppAndUpdateTime(){dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {preferences.get("curTime", '').then((curTime) => {preferences.put("lastTime", curTime);preferences.put("curTime", '');preferences.flush();console.log("上一次时间已更新,当前时间已清空");}).catch((err: Error) => {console.error(err.message)});}).catch((err: Error) => {console.error(err.message);});}
8. 用户登录方法 `login()` 和相关辅助方法:
login() {
? // 用户登录逻辑,包括密码验证、令牌解析、存储用户信息等操作
}uploadUserInfo() {
? // 将用户信息上传到本地存储
}getUserInfo() {
? // 获取本地存储的用户信息
}
9. 构建页面布局的方法 `build()`:
build() {
? // 构建页面布局,包括输入框、按钮、复选框等组件
}
这段代码实现了一个简单的登录页面,涵盖了用户输入、网络请求、数据存储等功能,并且使用 HarmonyOS 的一些模块来实现这些功能。
5.全代码
import router from '@ohos.router'
import storage from '@ohos.data.storage'
import App from '@system.app'
import Prompt from '@system.prompt'
import http from '@ohos.net.http'
import { RouterInfo } from '../../Pojo/RouterInfo'
import common from '@ohos.app.ability.common'
import dataPreference from '@ohos.data.preferences'
@Entry
@Component
struct Login {// todo 定义域@State username:string=""@State pwd:string=""@State allow:boolean = false@State upload:boolean = true@State uploadTag:boolean = false@State lastLocalTime:string=""httpUtil: http.HttpRequestcontext = getContext(this) as common.UIAbilityContext@State last:string=''Router = new RouterInfo("进入主页","pages/Books/Main","主页面")aboutToAppear() {let httpRequest = http.createHttp()this.httpUtil = httpRequest// todo 初始化上一次访问时间this.getPreTime()// todo 初始化当前时间this.getLocalTimeToPreference()// todo 初始化本地数据库的密码和用户名this.getUserInfo()}aboutToDisappear(){// todo 保存当前时间作为上一次的时间this.closeAppAndUpdateTime()}goTo(Router:RouterInfo){router.pushUrl({url: Router.url,params:{title:Router.message}},router.RouterMode.Single,err=> {if (err) {console.log("路由失败"+err.code+':'+err.message)}})}async jwt(jwt: string) {try {const res = await this.httpUtil.request(`192.168.137.1/readers/userinfo`, {method: http.RequestMethod.GET,extraData: { no: jwt },});let data = JSON.parse(res.result.toString());return data;} catch (error) {throw error;}}// 获取当前时间并存入用户首选项getLocalTimeToPreference(){const currentDate: Date = new Date();const currentYear: number = currentDate.getFullYear();const currentMonth: number = currentDate.getMonth() + 1; // 注意:月份从 0 开始,需要加 1const currentDay: number = currentDate.getDate();const currentHour: number = currentDate.getHours();const currentMinute: number = currentDate.getMinutes();const currentSecond: number = currentDate.getSeconds();const curTime = `北京时间:${currentYear}-${currentMonth}-${currentDay} ${currentHour}:${currentMinute}:${currentSecond}`;dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {preferences.put("curTime", curTime).then(_ => {preferences.flush();});}).catch((err: Error) => {console.error(err.message);});}// 获取上一次的时间--lastTimegetPreTime(){dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {if (!preferences.has("lastTime")) {console.log("数据并未能保存");} else {preferences.get("lastTime", 'null').then((value) => {this.last=value.toLocaleString()// AlertDialog.show({message:`上一次访问时间:${this.last}`})console.log("数据为:" + value);}).catch(_ => {console.log("读取失败");});}});}// 关闭应用时将lastTime置换为curTime,并将curTime替换为空值closeAppAndUpdateTime(){dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {preferences.get("curTime", '').then((curTime) => {preferences.put("lastTime", curTime);preferences.put("curTime", '');preferences.flush();console.log("上一次时间已更新,当前时间已清空");}).catch((err: Error) => {console.error(err.message)});}).catch((err: Error) => {console.error(err.message);});}// todo 函数定义域async login() {if (this.username && this.pwd && this.allow) {try {const res = await this.httpUtil.request(`192.168.137.1/readers/login`, {method: http.RequestMethod.GET,extraData: { no: this.username, pwd: this.pwd },});let jsonResult = res.result.toString();let responseObject = JSON.parse(jsonResult);if (responseObject['code'] === 200) {// todo 解析令牌const data = await this.jwt(responseObject['data']);// todo 上下文 -- 存储令牌AppStorage.SetOrCreate("info",data['data']['readerno'])// todo 是否将密码存储至本地if (this.upload===true) {this.uploadUserInfo()}// todo 跳转this.goTo(this.Router)}} catch (error) {console.error(error);Prompt.showDialog({message: "登录失败",});}} else {if (!this.username || !this.pwd) {Prompt.showDialog({message: "请输入用户名和密码",});} else if (!this.allow) {Prompt.showDialog({message: "请勾选允许登录选项",});}}}uploadUserInfo(){// 用户存储信息到本地,使用用户首选项dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {let user:{}={'username':this.username,'pwd':this.pwd}preferences.put("userInfo",JSON.stringify(user)).then(_ => {preferences.flush();});}).catch((err: Error) => {console.error(err.message);});}getUserInfo(){dataPreference.getPreferences(this.context, "myBookStore").then(preferences => {preferences.get("userInfo", '').then((userInfo) => {let user = JSON.parse(userInfo.toLocaleString())if (user) {this.uploadTag=truethis.username = user['username']this.pwd = user['pwd']}}).catch((err: Error) => {console.error(err.message)});}).catch((err: Error) => {console.error(err.message);});}build() {Column(){Column() {Text("掌上书店").fontColor('#096789').fontSize(70)this.displayLast("上一次访问时间:"+this.last)if (this.uploadTag===true){this.displayLast("本地已经存储密码")}}.margin({ bottom: 100 }).height('50%').justifyContent(FlexAlign.Center)Column(){Row(){// 用户名输入框TextInput({ placeholder: this.username===''? "请输入您的用户名":this.username }).type(InputType.Normal).width('80%').height(50).placeholderColor(Color.Black).backgroundColor('#ffd3d7d3').borderRadius(10).margin({ bottom: 10}).onChange(val=>{this.username=valconsole.log(val)})}Row(){// 密码输入框TextInput({ placeholder: this.pwd===''?"请输入您的密码":this.pwd }).type(InputType.Password).width('80%').height(50).placeholderColor(Color.Black).backgroundColor('#ffd3d7d3').borderRadius(10).onChange(val=>{this.pwd=valconsole.log(val)})}Row(){Row(){Checkbox().onChange((val:boolean)=>{this.upload=valconsole.log('Checkbox2 change is'+val)})Text("将密码存储到本地")}.width('98%').padding({left:30}).height('40')}.margin({ bottom: 40 })Row(){//登录按钮Button("登录").width(120).height(40).fontColor(Color.White).onClick(() => {this.login()}).backgroundColor('#ff5eb35b').margin({right:40}).borderStyle(BorderStyle.Dotted)// 注册按钮Button("注册").width(120).height(40).fontColor(Color.White).onClick(() => {router.pushUrl({url: "pages/Second"})}).backgroundColor('#ff5eb35b')}.justifyContent(FlexAlign.SpaceEvenly)}.width("100%").height("30%")Row(){Checkbox().onChange((val:boolean)=>{this.allow=valconsole.log('Checkbox2 change is'+val)})Text("点击代表同意相关使用条例与请求")}.width('90%').padding({left:30}).height('40')}.height('100%').width('100%').margin({bottom:20}).linearGradient({direction:GradientDirection.RightBottom,colors:[[0xAEE1E1, 0.0], [0xD3E0DC, 0.3], [0xFCD1D1, 1.0]]})}@Builder displayLast(message) {Row(){Text(message).fontColor("b#ffe7eae7")}.width("70%").height("40").backgroundColor("#ffe7eae7").borderRadius(20).padding({left:10}).margin({bottom:5})}
}
相关文章:
HarmonyOS Next 实现登录注册页面(ARKTS) 并使用Springboot作为后端提供接口
1. HarmonyOS next ArkTS ArkTS围绕应用开发在 TypeScript (简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集 ArkTS在TS的基础上扩展了struct和很多的装饰器以达到描述UI和状态管理的目的 以下代码是一个基于…...
咖啡即将“从天而降”,无人机外卖时代来袭
如今,在我国的一些城市,无人机配送咖啡已经从设想变为现实,开启了商业化的初步尝试。 当咖啡遇上无人机,奇妙场景开启 想象一下这样的画面:你在户外的露营地,慵懒地躺在帐篷里,或是在城市公园…...
kettle经验篇:Pentaho Repository 类型资源库卡顿问题
2024年马上就结束了,终于在结束前解决了困扰许久的一个问题:kettle的Pentaho Repository 资源库异常卡顿。所以在此也梳理、记录下2024年的最后一个大问题。 项目场景 工作中一个重要内容是数据中心项目,也就必不可少的要用到ETL技术&#x…...
python opencv的sift特征检测(Scale-Invariant Feature Transform)
sift 官方文档地址:https://docs.opencv.org/4.10.0/da/df5/tutorial_py_sift_intro.html 创建SIFT实例cv2.SIFT.create()特征检测sift.detect描述子sift.compute/sift.detectAndCompute画特征cv2.drawKeypoints 原图 特征点 代码 import cv2first ./12.pngsif…...
若依定时任务
表结构 目录 quartz框架 SysJobServiceImpl实现类 使用切点,在构造器执行的时候执行定时任务的构建(这个类是交给IOC容器的,所以这个时间点就是项目启动的时候)SysJobServiceImpl实现类的init方法创建任务 /*** 创建定时任务*/public static void createScheduleJob(Scheduler …...
k8s-node2 NotReady 节点NotReady如何解决?
从集群中移除 k8s-node2 [rootk8s-master ~]# kubectl delete node k8s-node2 node "k8s-node2" deleted重置 k8s-node2 登录到 k8s-node2 上,使用以下命令重置该节点,使其退出集群并恢复到初始状态: [rootk8s-node2 ~]# sudo k…...
Ubuntu通过mDNS实现局域网local域名和octoprint域名访问
OctoPrint是一个开源的3D打印机控制软件,它提供了一个Web界面,允许用户远程监控和管理3D打印机。通过USB连接到打印机后,用户可以使用任何带有Web浏览器的设备来控制打印作业,包括开始、停止、暂停打印,以及在打印过程…...
短视频矩阵账号管理技术源码搭建详解,支持OEM
一、引言 在短视频矩阵系统中,账号管理是至关重要的一环,它涉及到多平台账号的接入、用户信息的安全存储与高效管理、权限的精准控制以及账号数据的同步与更新等关键功能。一个健壮、灵活且安全的账号管理技术架构,能够为整个短视频矩阵系统的…...
【源码 导入教程 文档 讲解】基于springboot校园新闻管理系统源码和论文
可做计算机毕业设计JAVA、PHP、爬虫、APP、小程序、C#、C、python、数据可视化、大数据、文案 传统信息的管理大部分依赖于管理人员的手工登记与管理,然而,随着近些年信息技术的迅猛发展,让许多比较老套的信息管理模式进行了更新迭代…...
Spark SQL DML语句
【图书介绍】《Spark SQL大数据分析快速上手》-CSDN博客 《Spark SQL大数据分析快速上手》【摘要 书评 试读】- 京东图书 Spark本地模式安装_spark3.2.2本地模式安装-CSDN博客 DML(Data Manipulation Language,数据操作语言)操作主要用来对…...
开发微信小程序的过程与心得
起因 作为家长,我近期参与了学校的护学岗工作。在这个过程中,我发现需要使用水印相机来记录护学活动,但市面上大多数水印相机应用都要求开通会员才能使用完整功能。作为一名程序员,我决定利用自己的技术背景,开发一个…...
【1224】数据结构(sizeof/数组的长度定义/读取字符串函数/线性表长度/左值右值/静态变量/指针与引用)
1.对一维整型数组a的正确说明是 #define SIZE 10 (换行) int a[SIZE];说法是否正确? 正确 数组的SIZE可以用宏定义,但不能用变量 2.如有定义:char str[20];,能将从键盘输入的字符串“How are you”保存到 str 数组的语句是&#x…...
Android笔记(四十一):TabLayout内的tab不滚动问题
背景 假设二级页面是上面图片的布局,当进来时TabLayout和ViewPager2绑定完就马上调setCustomItem,跳转到最后一个tab页面时,会发现tab不滚动,手动滑一下ViewPager2时才会滚动tab到正确的位置 原因分析 调用TabLayoutMediator.at…...
基于pytorch的深度学习基础3——模型创建与nn.Module
三 模型创建与nn.Module 3.1 nn.Module 模型构建两要素: 构建子模块——__init()__拼接子模块——forward() 一个module可以有多个module; 一个module相当于一个运算,都必须实现forward函数; 每一个mod…...
Debian-linux运维-docker安装和配置
腾讯云搭建docker官方文档:https://cloud.tencent.com/document/product/213/46000 阿里云安装Docker官方文档:https://help.aliyun.com/zh/ecs/use-cases/install-and-use-docker-on-a-linux-ecs-instance 天翼云常见docker源配置指导:htt…...
Docker完整技术汇总
Docker 背景引入 在实际开发过程中有三个环境,分别是:开发环境、测试环境以及生产环境,假设开发环境中开发人员用的是jdk8,而在测试环境中测试人员用的时jdk7,这就导致程序员开发完系统后将其打成jar包发给测试人员后…...
在JavaScript文件中定义方法和数据(不是在对象里定以数据和方法,不要搞错了)
在对象里定以数据和方法看这一篇 对象字面量内定义属性和方法(什么使用const等关键字,什么时候用键值对)-CSDN博客https://blog.csdn.net/m0_62961212/article/details/144788665 下是在JavaScript文件中定义方法和数据的基本方式ÿ…...
python爬虫爬抖音小店商品数据+数据可视化
爬虫代码 爬虫代码是我调用的数据接口,可能会过一段时间用不了,欢迎大家留言评论,我会不定时更新 import requests import time cookies {token: 5549EB98B15E411DA0BD05935C0F225F,tfstk: g1vopsc0sQ5SwD8TyEWSTmONZ3cA2u6CReedJ9QEgZ7byz…...
关于 覆铜与导线之间间距较小需要增加间距 的解决方法
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/144776995 长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV…...
uniapp中Nvue白屏问题 ReferenceError: require is not defined
uniapp控制台输出如下 exception function:createInstanceContext, exception:white screen cause create instanceContext failed,check js stack ->Uncaught ReferenceError: require is not defined 或者 exception function:createInstanceContext, exception:white s…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

