详细教程 - 从零开发 鸿蒙harmonyOS应用 第四节 (鸿蒙Stage模型 登录页面 ArkTS版 推荐使用)

在鸿蒙OS中,Ability是应用程序提供的抽象功能,可以理解为一种功能。在应用程序中,一个页面即一种能力,如登录页面,即具有登录功能的能力。以下是对鸿蒙新建项目的登录代码功能的详细解读和工作流程的描述:

  1. 新建Ability:在DevEco Studio中,选择一个Empty Ability工程模板,然后在src/main/ets/entryability目录下生成一个Ability文件EntryAbility.ts。

  2. 新建登录页面:在src/main/ets/pages目录下生成一个Login页面,这是基于Ability实现的应用的入口页面。你可以在Login页面中根据业务需要实现入口页面的功能。

  3. 实现登录功能:在登录页面中,你需要实现用户输入用户名和密码,点击登录按钮后,验证用户名和密码的正确性,如果验证通过,则跳转到主页面。

  4. 页面跳转及传参:页面间的导航可以通过页面路由router模块来实现。页面路由模块根据页面url找到目标页面,从而实现跳转。通过页面路由模块,可以使用不同的url访问不同的页面,包括跳转到Ability内的指定页面、用Ability内的某个页面替换当前页面、返回上一页面或指定的页面等。通过params来传递参数。

  5. Ability生命周期:能力有四种生命周期状态:INITIAL (初始态)、INACTIVE (未激活)、ACTIVE (激活)、BACKGROUND (后台)。在Ability的生命周期中,你需要重写onStart(), onActive(), onInactive(), onBackground(), onForeground(), onStop()等方法,来实现Ability的生命周期回调内容。

当然你可以忽略上面,让我们来直接创建带有登录功能的项目模板【Login Ability】,如下图:

直接next:

点击finish完成创建,创建成功后,本地预览

工程目录结构(API Version 8~9)

应用/服务支持API Version 4~9。API Version 4~7和API Version 8~9的构建工具和构建插件不同。其中,API Version 4~7构建体系是由Gradle构建工具和构建插件组成;API Version 8~9构建体系是由Hvigor构建工具和构建插件组成。所以API Version 4~7和API Version 8~9的工程目录结构存在差异。下面按照不同开发语言分别介绍API Version 4~7和API Version 8~9的工程目录结构。

ArkTS工程目录结构(Stage模型)

ArkTS Stage模型支持API Version 9,其工程目录结构如下图所示

  • AppScope > app.json5:应用的全局配置信息。
  • entry:应用/服务模块,编译构建生成一个HAP。
  • src > main > ets:用于存放ArkTS源码。
  • src > main > ets > entryability:应用/服务的入口。
  • src > main > ets > pages:应用/服务包含的页面。
  • src > main > resources :用于存放应用/服务所用到的资源文件,如图形、多媒体、字符串、布局文件等。关于资源文件的详细说明请参考资源文件的分类
资源目录 资源文件说明
base>element 包括字符串、整型数、颜色、样式等资源的json文件。每个资源均由json格式进行定义,例如:boolean.json:布尔型 color.json:颜色 float.json:浮点型 intarray.json:整型数组integer.json:整型 pattern.json:样式 plural.json:复数形式 strarray.json:字符串数组 string.json:字符串值
base>media 多媒体文件,如图形、视频、音频等文件,支持的文件格式包括:.png、.gif、.mp3、.mp4等。
rawfile 用于存储任意格式的原始资源文件。rawfile不会根据设备的状态去匹配不同的资源,需要指定文件路径和文件名进行引用。

一、目录文件介绍

下面我们对项目代码进行一个详细的分析解读:

(1)src > main > ets > entryability*

bash 复制代码
import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import type Want from '@ohos.app.ability.Want';
import type window from '@ohos.window';

/**
 * Lift cycle management of Ability.
 */
export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent("pages/LoginPage", (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }

  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

这段代码是鸿蒙应用的入口Ability,它继承自UIAbility类,用于管理Ability的生命周期和窗口阶段。下面是对这段代码的详细解读:

  1. 导入模块:首先,代码导入了必要的模块,包括AbilityConstant、hilog、UIAbility、Want和window。

  2. Ability生命周期管理:EntryAbility类继承自UIAbility类,重写了onCreate、onDestroy、onForeground和onBackground等方法,用于管理Ability的生命周期。

  3. 窗口阶段管理:EntryAbility类还重写了onWindowStageCreate和onWindowStageDestroy方法,用于管理窗口阶段。在onWindowStageCreate方法中,加载了登录页面LoginPage,并在加载成功后打印日志。

  4. 日志打印:在每个方法中,都使用了hilog模块打印了日志,用于调试和跟踪代码执行情况。

这样写的原因是,鸿蒙应用的入口Ability需要管理Ability的生命周期和窗口阶段,以及加载应用的主页面。同时,打印日志可以帮助开发者调试代码和跟踪代码执行情况。

它继承自UIAbility类,用于管理Ability的生命周期和窗口阶段。下面是对这段代码的详细解读:

typescript 复制代码
import type AbilityConstant from '@ohos.app.ability.AbilityConstant';
import hilog from '@ohos.hilog';
import UIAbility from '@ohos.app.ability.UIAbility';
import type Want from '@ohos.app.ability.Want';
import type window from '@ohos.window';

这部分代码导入了必要的模块,包括AbilityConstant、hilog、UIAbility、Want和window。

typescript 复制代码
export default class EntryAbility extends UIAbility {

这里定义了一个名为EntryAbility的类,它继承自UIAbility类。

typescript 复制代码
 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
   hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
 }

onCreate方法在Ability创建时被调用,这里打印了一条日志。

typescript 复制代码
 onDestroy(): void {
   hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
 }

onDestroy方法在Ability销毁时被调用,这里打印了一条日志。

typescript 复制代码
onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    windowStage.loadContent("pages/LoginPage", (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }

onWindowStageCreate方法在窗口阶段创建时被调用,这里加载了登录页面LoginPage,并在加载成功后打印了一条日志。

typescript 复制代码
onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

onWindowStageDestroy方法在窗口阶段销毁时被调用,这里打印了一条日志。

typescript 复制代码
onForeground(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
}

onForeground和onBackground方法分别在Ability进入前台和后台时被调用,这里分别打印了一条日志。

(2)src > main > pages>

在鸿蒙Login Ability项目中,CustomerServicePage.ets、LoginPage.ets、MinePage.ets、PrivacyPage.ets、RegistrationSuccessPage.ets 都是Ability内的页面12。每个页面都有其特定的功能和作用。具体来说:

  • CustomerServicePage.ets:这个页面用来提供客户服务信息的。用户可以在这个页面上查看和获取客户服务相关的信息,在系统中单击遇见问题按钮跳转到此页面。

  • LoginPage.ets:这个页面是登录页面。它的主要功能是让用户输入他们的登录凭据(如用户名和密码),以便验证他们的身份并允许他们访问应用的其他部分。

  • MinePage.ets:这个页面是用户的个人页面或者个人中心。用户可以在这个页面上查看和管理他们的个人信息和设置。

  • PrivacyPage.ets:这个页面是用来显示应用的隐私政策的。用户可以在这个页面上查看应用如何收集、使用和存储他们的个人数据的信息。

  • RegistrationSuccessPage.ets:这个页面是用户成功注册后显示的页面。它可能会显示一些欢迎信息,或者提供一些关于下一步操作的指导。

具体的功能可能会根据实际的应用需求和设计有所不同。在实际的开发过程中,开发者可以根据需要在这些页面中实现各种功能。例如,页面间的导航可以通过页面路由router模块来实现。页面路由模块根据页面url找到目标页面,从而实现跳转。通过params来传递参数。在使用页面路由之前,需要先导入router模块。页面跳转的几种方式,根据需要选择一种方式跳转即可。具体的实现细节,在评论区互动,我会进一步详细出教程

下面主要我们来介绍一下 LoginPage 页面:

LoginPage
typescript 复制代码
import router from '@ohos.router';
import MediaQueryModel from '../model/MediaQueryModel';
import { CommonConstants } from '../common/constants/CommonConstants';
import { PrivacyStatementComponent } from '../view/PrivacyStatementComponent';
import { LoginComponent } from '../view/LoginComponent';

/**
 * This template implements the Login function.
 * First register personal details. Log in after entering the username and password.
 * Click the button at the bottom to ask for help and check the privacy statement.
 * Developers can save username and password by Preference or Relational Database.
 */
@Entry
@Component
struct LoginPage {
  aboutToAppear() {
    MediaQueryModel.register();
  }

  aboutToDisappear() {
    MediaQueryModel.unRegister();
  }

  build() {
    Column() {
      this.Title()

      Scroll() {
        Column() {
          LoginComponent()

          Blank()

          PrivacyStatementComponent()
        }
        .height(CommonConstants.SCROLL_HEIGHT_PERCENT)
        .constraintSize({ minHeight: $r('app.float.scroll_min_height') })
        .alignItems(HorizontalAlign.Start)
        .padding($r('app.float.login_operation_area_padding'))
      }
      .layoutWeight(CommonConstants.LOGIN_SCROLL_LAYOUT_WEIGHT)
    }
    .width(CommonConstants.LOGIN_PAGE_WIDTH_PERCENT)
    .backgroundColor($r('app.color.login_page_background'))
  }

   @Builder Title() {
    Row() {
      Image($r('app.media.ic_back'))
        .width($r('app.float.image_size'))
        .height($r('app.float.image_size'))
        .margin({
          left: $r('app.float.image_margin_left'),
          right: $r('app.float.image_margin_right')
        })
        .onClick(() => {
          router.back();
        })

       Text($r('app.string.title'))
        .fontSize($r('app.float.title_text_size'))
        .fontColor($r('app.color.title'))
        .fontWeight(CommonConstants.TITLE_FONT_WEIGHT)
    }
    .width(CommonConstants.FULL_WIDTH_PERCENT)
    .height($r('app.float.title_height'))
  }
}

这段代码是鸿蒙应用的登录页面,它使用了鸿蒙的UI框架来构建用户界面。下面是对这段代码的详细解读:

typescript 复制代码
import router from '@ohos.router';
import MediaQueryModel from '../model/MediaQueryModel';
import { CommonConstants } from '../common/constants/CommonConstants';
import { PrivacyStatementComponent } from '../view/PrivacyStatementComponent';
import { LoginComponent } from '../view/LoginComponent';

这部分代码导入了必要的模块,包括routerMediaQueryModelCommonConstantsPrivacyStatementComponentLoginComponent

typescript 复制代码
@Entry
@Component
struct LoginPage {}

这里定义了一个名为LoginPage的结构体,它被标记为应用的入口组件

typescript 复制代码
aboutToAppear() {
   MediaQueryModel.register();
}

aboutToDisappear() {
   MediaQueryModel.unRegister();
}

aboutToAppearaboutToDisappear方法分别在页面即将出现和即将消失时被调用,这里分别注册和注销了媒体查询模型。

typescript 复制代码
//方法用于构建页面的布局。
build() {
	//创建一个列布局,它的子组件会垂直排列
    Column() {
    	//添加标题组件,这是通过Title方法创建的。
      	this.Title()
      	//创建一个滚动组件,它的子组件可以滚动。
	    Scroll() {
	    	//在滚动组件中创建一个列布局。
	        Column() {
	        	//添加登录组件,这是通过LoginComponent方法创建的。
	          	LoginComponent()
				//添加一个空白组件,用于提供间隔。
	          	Blank()
				//添加隐私声明组件,这是通过PrivacyStatementComponent方法创建的。
	          	PrivacyStatementComponent()
	        }
	        .height(CommonConstants.SCROLL_HEIGHT_PERCENT)
	        .constraintSize({ minHeight: $r('app.float.scroll_min_height') })
	        .alignItems(HorizontalAlign.Start)
	        .padding($r('app.float.login_operation_area_padding'))//设置滚动组件的高度、最小高度、子组件的水平对齐方式和内边距。
	      }
	      .layoutWeight(CommonConstants.LOGIN_SCROLL_LAYOUT_WEIGHT)//设置滚动组件的布局权重,这决定了它在父组件中占据的空间比例
    }
    .width(CommonConstants.LOGIN_PAGE_WIDTH_PERCENT)
    .backgroundColor($r('app.color.login_page_background'))//设置列布局的宽度和背景颜色。
  }

build方法用于构建页面的布局,这里构建了一个包含标题、登录组件和隐私声明组件的滚动列。

typescript 复制代码
//这里定义了一个名为Title的方法,它被标记为构建器,用于构建标题组件。
@Builder Title() {
	//创建一个行布局,它的子组件会水平排列。
    Row() {
    	//添加一个图片组件,图片的资源路径是从资源文件中获取的。
      	Image($r('app.media.ic_back'))
        	.width($r('app.float.image_size'))
        	.height($r('app.float.image_size'))//设置图片的宽度和高度,这些值是从资源文件中获取的。
       	 	.margin({
          		left: $r('app.float.image_margin_left'),
          		right: $r('app.float.image_margin_right')
       		})//设置图片的左右边距,这些值是从资源文件中获取的。
        .onClick(() => {
        	 //设置图片的点击事件,当点击图片时,会调用路由的back方法,返回上一页面。
         	 router.back();
        })
	   //添加一个文本组件,文本的内容是从资源文件中获取的。
       Text($r('app.string.title'))
        .fontSize($r('app.float.title_text_size'))
        .fontColor($r('app.color.title'))
        .fontWeight(CommonConstants.TITLE_FONT_WEIGHT)//设置文本的字体大小、颜色和粗细,这些值是从资源文件和常量文件中获取的。
    }
    .width(CommonConstants.FULL_WIDTH_PERCENT)
    .height($r('app.float.title_height'))
    //设置行布局的宽度和高度,这些值是从常量文件和资源文件中获取的
  }

Title方法用于构建页面的标题,这里构建了一个包含返回图标和标题文本的行。

以上就是对这段代码的详细解读。这样写的原因是,鸿蒙的UI框架提供了一种声明式的方式来构建用户界面,使得代码更加简洁和易于理解。

结语

其它版本:详细教程 - 从零开发 Vue 鸿蒙应用 第二节 (鸿蒙Stage模型 登录页面 JS版)

有写的不对的地方,欢迎大家评论区指错批评!!!

相关推荐
mldong2 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排3 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60613 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角5 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!5 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰5 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi6 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen7 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马8 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒8 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端