目錄
前言
一、準備工作
二、實戰開發
2.2、頁面路由開發
2.2.1、創建常量
2.2.2、創建字符串資源
2.2.3、創建float資源
2.2.4、創建color資源
2.2.5、創建數據實體
2.2.6、創建頁面路由表
2.2.9、頁面路由跳轉及傳參
2.2.10、處理頁面返回鍵
前言
寫這個系列的目標是準備通過幾篇文章的介紹,和大家一起快速入門HarmonyOS應用的開發。初步打算是主要通過代碼實戰的形式去介紹,基本的語法和使用還是建議大家先閱讀官網的文檔說明。OK,話不多說,咱們開始。
一、準備工作
首先,最全面的學習資料肯定是官網文檔,所以需要快速掌握文檔的對應位置,這里把開發中經常用到文檔入口都羅列在下面了,按需自取:
開發指南? ? ? ? ?API文檔? ? ? ? ?最佳實踐? ? ? ? ?FAQ? ? ? ??示例代碼
其次,注意搜索時左側菜單可以選擇類別,比如這里可以勾選全部:
OK,接著咱們下載開發工具:下載與安裝DevEco Studio,這個沒什么好說的,下載完了之后一步一步安裝即可。
接著學習開發語言可以參考如下內容,鴻蒙中使用的ArkTS是基于TypeScript做了擴展:
學習ArkTS語言和應用框架中的ArkTs(方舟編程語言)
準備工作就做到這里,接下來就可以上手開發了,今天咱們首先來學習路由如何使用。
二、實戰開發
2.1、Navigation簡介
Navigation主要用于實現Navigation頁面(NavDestination)間的跳轉,支持在不同Navigation頁面間傳遞參數,提供靈活的入棧出棧操作,方便快捷的實現對不同頁面的訪問和復用。關于Navigation更多的介紹及詳細使用大家可以參考:
組件導航(Navigation) (推薦)
2.2、頁面路由開發
首先我們先創建一個空工程,這里可以根據公司規范或者個人習慣修改相關文件名。在src/main/ets/pages目錄下新建navigation文件夾,將Index.ets移動到該文件夾下,并修改文件名為NavigationPage.ets,并且修改代碼中Index名稱為NavigationPage,同時還需要修改EntryAbility文件中默認加載的頁面路徑:
上面的NavigationPage作為整個工程頁面路由棧的根頁面,你可以把它理解為一個相冊,我們使用@Entry來修飾它,并且使用Navigation作為它的組件樹的根節點。然后我們需要實現的APP的各個展示頁面就是相冊里面的一張一張的照片,我們使用@Component來修飾它,并且使用NavDestination作為它們的組件樹的根節點。簡單理解就是:Navigation是容器,NavDestination是頁面。在今天的例子中,我們會創建兩個頁面MainPage和OtherPage。
今天由于是本系列的第一篇,所以一些基礎工作我也會介紹一下,后續的文章中將不再贅述。
2.2.1、創建常量
在工程的src/main/ets 目錄下新建文件夾constants,用來存放項目中需要用到的常量字段,這里我們創建兩個文件:CommonConstant存放公共常量,PageConstant存放頁面名稱,代碼如下:
export class CommonConstant {static readonly FULL_PERCENT: string = '100%'static readonly PAGEINFO_KEY: string = 'PageInfo'static readonly EXIT_INFO: string = '再按一次退出應用'static readonly PRE_TIME: number = 0static readonly EXIT_TIME: number = 2000
}
export class PageConstant{static readonly PAGE_MAIN: string = 'MainPage'static readonly PAGE_OTHER: string = 'OtherPage'
}
2.2.2、創建字符串資源
在resources/base/elment/string.json文件中添加項目中需要用到的字符串資源:
{"string": [{"name": "tip_main_page","value": "我是主頁點我跳轉"},{"name": "tip_other_page","value": "我是其它頁面"}]
}
2.2.3、創建float資源
在resources/base/elment/float.json文件中添加項目中需要用到的字體大小fp和組件大小vp資源:
{"float": [{"name": "fp_20","value": "20fp"},{"name": "vp_100","value": "100vp"}]
}
2.2.4、創建color資源
在resources/base/elment/color.json文件中添加項目中需要用到的顏色資源:
{"color": [{"name": "color_primiry","value": "#57BE6A"}]
}
2.2.5、創建數據實體
在src/main/ets下新建model文件夾,在該文件夾下新建DemoData.ets文件,在這個文件里我們創建頁面間傳值所需的數據類,這里介紹了兩種方式interface和class,都可以定義所需的實體:
// MainPage傳遞參數的數據類
export interface ParamData {name: string
}// OtherPage回傳的數據類
export class BackData {result?: stringconstructor(result: string) {this.result = result}
}
2.2.6、創建頁面路由表
在src/main/ets/pages/navigaion目錄下新建PagesMapBuilder.ets文件,作為項目的頁面路由表:
import { PageConstant } from "../../constants/PageConstant";
import { MainPage } from "../MainPage";
import { OtherPage } from "../OtherPage";@Builder
export function PagesMapBuilder(name: string) {if (name===PageConstant.PAGE_MAIN) {MainPage()}else if (name===PageConstant.PAGE_OTHER){OtherPage()}
}
2.2.7、創建Navigation根容器
在NavigationPage頁面中,我們實例化了一個NavPathStack對象:
// 頁面路由棧
@Provide(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack = new NavPathStack()
從名字也能看出它是用來管理頁面路由的路由棧對象,這里我們使用了@Provide這個裝飾器來修飾,它一般是與@Consume成對使用,用于與后代組件的雙向數據同步、狀態數據在多個層級之間傳遞的場景。使用詳情可以參考:@Provide裝飾器和@Consume裝飾器:與后代組件雙向同步
然后在build()函數中,我們創建Navigation組件并且綁定導航控制器和頁面路由表:
import { CommonConstant } from '../../constants/CommonConstant'
import { PagesMapBuilder } from './PagesMapBuilder'@Entry
@Component
struct NavigationPage {// 頁面路由棧@Provide(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack = new NavPathStack()build() {Navigation(this.pageStack).hideTitleBar(true).hideToolBar(true).hideNavBar(true).mode(NavigationMode.Stack).navDestination(PagesMapBuilder)}
}
這里的build()函數是用于定義自定義組件的聲明式UI描述,自定義組件必須定義build()函數。從這里也就看出了HarmonyOS應用的UI是使用的聲明式UI,這里提到了它是用于自定義組件的UI描述,因此咱們這里的NavigationPage也是自定義組件,你可以理解在HarmonyOS應用中:一切皆組件!
關于自定義組件的使用可以參考:創建自定義組件
可以看到,我們代碼中的@Component? struct正是符合這個結構的,至于最上面的@Entry,那是因為它裝飾的自定義組件是UI頁面的入口。
2.2.8、創建NavDestination子頁面
在src/main/ets/pages文件夾下新建MainPage.ets文件,在這個文件中首先定義路由棧對象,承接上文中的@Provide,這里我們可以直接使用@Consume來定義:
@Consume(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack
然后在build()函數中創建NavDestination為根節點的組件樹,這里面我們僅添加一個Text文本用于展示:
import { CommonConstant } from "../constants/CommonConstant"@Component
export struct MainPage {@Consume(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack@State content: string | Resource = $r('app.string.tip_main_page')build() {NavDestination() {Column() {Text(this.content).fontSize($r('app.float.fp_20')).fontColor(Color.Blue).fontWeight(FontWeight.Bold)}.width(CommonConstant.FULL_PERCENT).height(CommonConstant.FULL_PERCENT).justifyContent(FlexAlign.Center)}.hideTitleBar(true)}
}
這里的@State同樣是一個狀態管理的裝飾器,用它修飾的變量在組件內數據變更時可以引起UI的自動刷新,具體使用可以參考:@State裝飾器:組件內狀態
然后以同樣的方式創建另一個頁面OtherPage.ets:
import { CommonConstant } from "../constants/CommonConstant"@Component
export struct OtherPage {@Consume(CommonConstant.PAGEINFO_KEY) pageStack: NavPathStack@State content: string | Resource = $r('app.string.tip_other_page')build() {NavDestination() {Column() {Text(this.content).fontSize($r('app.float.fp_20')).fontColor(Color.Blue).fontWeight(FontWeight.Bold).onClick(() => {let backData = new BackData('我是Other數據')this.pageStack.pop(backData)})}.width(CommonConstant.FULL_PERCENT).height(CommonConstant.FULL_PERCENT).justifyContent(FlexAlign.Center)}.hideTitleBar(true)}
}
2.2.9、頁面路由跳轉及傳參
首先在NavigationPage的aboutToAppear()回調中添加第一個加載的頁面視圖:
aboutToAppear(): void {this.pageStack.pushPath({ name: PageConstant.PAGE_MAIN }, false)
}
aboutToAppear()是自定義組件的一個生命周期函數,在組件即將出現時回調該接口,具體時機為在創建自定義組件的新實例后,在執行其build函數之前執行,詳情可以參考:
自定義組件生命周期
然后在MainPage中創建需要傳遞的參數:
paramData: ParamData = { name: '我是MainPage數據' }
在MainPage中的Text文本的點擊事件里,跳轉到OtherPage頁面,并將上面的數據作為參數傳遞過去,同時在onPop回調中可以接收OtherPage頁面回傳的參數,如果不需要回傳參數onPop回調可以不用寫:
.onClick(() => {// 頁面跳轉,傳遞參數到Other頁面,并通過onPop回調接收Other頁面回傳的數據this.pageStack.pushPath({name: PageConstant.PAGE_OTHER, param: this.paramData, onPop: (popInfo: PopInfo) => {let backData = popInfo.result as BackDatathis.content = backData.result}})})
接著在OtherPage頁面中接收來自MainPage傳遞的參數,這里接收參數我們介紹兩種方式:
第一種:使用NavDestination的onReady()函數進行接收:
.onReady((context: NavDestinationContext) => {this.paramData = context.pathInfo.param as ParamDataif (this.paramData) {this.content = this.paramData.name}})
第二種:在aboutToAppear()生命周期函數中通過pageStack的getParamByIndex()函數接收:
aboutToAppear(): void {this.paramData = this.pageStack.getParamByIndex(this.pageStack.size() - 1) as ParamDataif (this.paramData) {this.content = this.paramData.name}}
然后在OtherPage的Text文本的點擊事件中我們將需要回傳的參數通過pageStack的pop(xxx)方法進行回傳:
.onClick(() => {let backData = new BackData('我是Other數據')this.pageStack.pop(backData)})
2.2.10、處理頁面返回鍵
在Android中我們經常可以看到在點擊Back鍵時會提示:再按一次退出應用,雖然現在很多手機隱藏了返回鍵,但是我們通過側滑仍然可以出發頁面返回,那如果想要實現上面的效果該怎么做呢?
其實原理是類似的,在HarmonyOS中,我們可以監聽頁面的onBackPress()事件,在這個函數中處理連續點按退出應用的邏輯:
import { CommonConstant } from '../../constants/CommonConstant'
import { common } from '@kit.AbilityKit'@Entry
@Component
struct NavigationPage {private context = this.getUIContext().getHostContext() as common.UIAbilityContextprivate preTime: number = CommonConstant.PRE_TIMEpromptAction = this.getUIContext().getPromptAction()// 2秒內連續點按/側滑后關閉當前應用onBackPress(): boolean | void {let currentTime = new Date().getTime()let flag = currentTime - this.preTimeif (flag > CommonConstant.EXIT_TIME) {this.preTime = currentTimethis.promptAction.showToast({ message: CommonConstant.EXIT_INFO })return true} else {this.context.terminateSelf()}return false}
}
最后來看一下實現的效果吧:
實現效果錄屏
完整代碼:HarmonyDemos
OK,今天的內容到這里就要和大家說再見了,咱們下期再會!
祝:工作順利,前程似錦!