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})}
}