HarmonyOS:去繁化簡,實戰(zhàn)整理的開發(fā)者清單

引言

由于公司開始支持鴻蒙生態(tài)肉瓦,小編也開啟了鴻蒙純血NEXT版本的應用開發(fā)银还。

本篇主要整理總結(jié)實戰(zhàn)項目中遇到的問題及重點知識內(nèi)容戒财。適合使用ArkTS進行鴻蒙NEXT及以上版本開發(fā)的初學者列吼、進階學習者理郑。

內(nèi)容分為以下幾個維度柒爵,歡迎大家一起交流學習。

ArkTS 語言

使用ArkTs語言進行開發(fā)唁奢,了解如下兩點即可

1. 數(shù)據(jù)類型

ArkTS支持的數(shù)據(jù)類型如下:

Object驮瞧、string论笔、number、boolean蒜埋、enum 整份、Array籽孙、union犯建、void适瓦、aliases、Record否彩、Map 等列荔。

下面列舉一些個例的特性:

// string
undefined == name?:string

// Array
let name: string[] = ['rex','bob']

// union | 聯(lián)合類型
type Animal = Cat | Dog
let animal : Animal = new Cat()
animal = new Dog()

// aliases | 匿名類型
type Predicate <T> = (x: T) => Boolean;
type NullableObject = Object | null;

// Record<K,V> | Record 與 Map 的區(qū)別是 Record 不需要 new肌毅,Map 需要 new
let map: Record<string, number> = {
  'John': 25,
  'Mary': 21,
}

2. 語法特點

ArkTS的語法與其他前端語言大同小異,下面列舉一些個例的特性:

// Rest參數(shù)
fun sum(...numbers: number[])
sum()
sum(1,2,3)
 
// 定義回調(diào)
type trigFunc = (x:number) => number
function do_action(f: trigFunc)

// 閉包
function f(): () => number {
  let count = 0;
  return (): number => { count++; return count; }
}
let z = f();
z(); // 返回:1
z(); // 返回:2

// 可選參數(shù)
function hello(name?: string) // name == undefined
function multiply(n: number, coeff: number = 2)
nultiply(1)

// 字段不復值時默認值是 undefined

// 構(gòu)造函數(shù)需要使用關(guān)鍵字
constructor(n: string, a: number)

// 模塊導出
export let Origin = new Point(0, 0);
export function Distance(p1: Point, p2: Point): number{ *** }

// 模塊導入
import * as Utils from './utils' // Utils.X
import { X, Y } from './utils'
X // 表示來自utils的X
Y // 表示來自utils的Y

// 聲明
readonly height : number = 1 //只讀 
let hi: string = 'hello' //變量
const hello: string = 'hello' //常量

// 空安全
let x: number | null = null

// 接口 interface
interface W {
  bundleName: string
  action: string
  entities: string[]
}
let wantInfo: W = {
  bundleName: 'com.huawei.hmos.browser',
  action: 'ohos.want.action.viewData',
  entities: ['entity.system.browsable']
}

PS:需要注意的是锭汛,字符串里插入變量要使用`符號而不是單引號或雙引號唤殴,如下:

Text(`插入變量到字符串中的值為${this.number}`)

HarmonyOS 的項目結(jié)構(gòu)

關(guān)于 HarmonyOS 的項目包結(jié)構(gòu)朵逝,我們暫時不需要做到全盤掌握,了解如下幾個知識點即可:

1. 項目類型

創(chuàng)建項目分為兩種類型啤咽,分別是 app(應用)宇整、atomicService(元服務(wù)

image.png

這兩種類型的項目創(chuàng)建后的包結(jié)構(gòu)是一樣的鳞青,代碼編輯也一致臂拓。重點差異如下:

  • 元服務(wù)類似于微信小程序习寸,用戶可直接在手機的負一層頁面搜索使用融涣,無需下載
  • 元服務(wù)的開發(fā)api是應用的開發(fā)api的子集,即有些api在開發(fā)應用時可用剃斧,在開發(fā)元服務(wù)時不可用幼东。

2. 模塊類型

創(chuàng)建模塊分為三種類型根蟹,分別是 hap糟秘、har尿赚、hsp

image.png
  • HAP:應用安裝和運行的基本單元,分為兩種類型:entry和feature
  • HAR:靜態(tài)共享包 (可以理解為封裝的 Library屋讶,里面可以存放代碼和資源皿渗,提供給 hap 或者 har 模塊進行引用)
  • HSP:動態(tài)共享包(一般應用不常用)

3. 重點文件

  • app.json5 :bundleType 標識 元服務(wù)(atomicService)或 應用(app)
  • module.json5 :stage模型模塊配置文件乐疆,type 標識模塊類型(entry约计、hap煤蚌、har尉桩、share)
  • oh-package.json5 :配置三方包聲明文件的入口及包名

最后展示一張項目的包結(jié)構(gòu)截圖:

image.png

UI 開發(fā)中的實用技巧

1. 單位

  • fp: 字體像素單位蜘犁,隨系統(tǒng)字體大小設(shè)置變化
  • vp: 密度像素單位
//使用示例
Text('示例').fontSize('16fp').widht('100vp')

2. @Extend

定義擴展組件樣式

@Extend(Column)
function ColumnStyle() {
  .width('100%')
  .borderRadius(24)
  .backgroundColor(Color.White)
  .padding({ left: 12, right: 12, bottom: 4, top: 4 })
}

Column(){}.ColumnStyle()

3. @Styles

定義組件重用樣式

@Styles fancy() {
  .width(200)
  .height(this.heightValue)
  .backgroundColor(Color.Yellow)
  .onClick(() => {
  this.heightValue = 200
  })
}

Text().fancy()

4. 自定義組件 @Builder 和 @BuilderParam

@Component
struct Child {
  @Builder FunABuilder0() {}
  @BuilderParam aBuilder0: () => void = this.FunABuilder0;

  build() {
    Column() {
      this.aBuilder0()
    }
  }
}

@Entry
@Component
struct Parent {
  @Builder componentBuilder() {
    Text(`Parent builder `)
  }

  build() {
    Column() {
      Child({ aBuilder0: this.componentBuilder })
    }
  }
}

5. 生命周期

  • 自定義組件:@Component裝飾的UI單元奏窑,可以調(diào)用組件的生命周期屈扎。
  • 頁面:可以由一個或者多個自定義組件組成鹰晨,只有被@Entry裝飾的組件才可以調(diào)用頁面的生命周期模蜡。
    • onPageShow:頁面每次顯示時觸發(fā)一次,包括路由過程闯传、應用進入前臺等場景丸边,僅@Entry裝飾的自定義組件生效。
    • onPageHide:頁面每次隱藏時觸發(fā)一次,包括路由過程骄呼、應用進入后臺等場景蜓萄,僅@Entry裝飾的自定義組件生效嫉沽。
    • onBackPress:當用戶點擊返回按鈕時觸發(fā)俏竞,僅@Entry裝飾的自定義組件生效魂毁。
    • aboutToAppear:組件即將出現(xiàn)時回調(diào)該接口席楚,具體時機為在創(chuàng)建自定義組件的新實例后烦秩,在執(zhí)行其build()函數(shù)之前執(zhí)行只祠。
    • aboutToDisappear:aboutToDisappear函數(shù)在自定義組件析構(gòu)銷毀之前執(zhí)行。不允許在aboutToDisappear函數(shù)中改變狀態(tài)變量牺氨,特別是@Link變量的修改可能會導致應用程序行為不穩(wěn)定猴凹。

HarmoneyOS 的狀態(tài)管理

1. 組件的狀態(tài)管理

建議看一遍官網(wǎng)的示例

2. 應用的狀態(tài)管理

PS:重點提一下 LocalStorage 和 AppStorage 的區(qū)別郊霎,LocalStorage 是頁面級存儲爷绘、頁面內(nèi)共享,而 AppStorage 是可以跨 Ability 共享的猾昆。(即適用于多hap項目)

應用開發(fā)中常用方法

1. Toast 的使用

promptAction.showToast({
  message: $r('app.string.success_message'),
  duration: 2000
})

2. Preferences 的使用

import dataPreferences from '@ohos.data.preferences';

//聲明
let dataPreferencesManager: dataPreferences.Preferences = {} as dataPreferences.Preferences;

//獲取實例
let options: dataPreferences.Options = { name: 'myStore', dataGroupId:'myId' };
dataPreferences.getPreferences(this.context, options, (err: BusinessError, val: dataPreferences.Preferences) => {
    if (err) {
        return;
    }
    preferences = val;
})

//put
dataPreferencesManager.push(key,value)
dataPreferencesManager.flush()

3. Context

/// 實現(xiàn)全局Context
// 在 EntryAbility 的 create 方法中綁定上下文
AppStorage.setOrCreate('context', this.context);

//獲取全局Context
AppStorage.get('context')


/// UI頁面獲取局部Context
const CONTEXT: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;

4. JSON 與 Object 的轉(zhuǎn)換

/// JSON to Object
/// 方案一:
class A {
  v: number = 0
  s: string = ''
  fromJson (str: string) {
    let tmpStr: Record<string, Object> = JSON.parse(str);
    if (tmpStr.add != undefined) {
      this.v = tmpStr.v as number;
      this.s = tmpStr.s as string;
    }
  }
}
/// 方案二:
let json: string = '{"name":"rex","age":"10"}'
class Student {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
let student = JSON.parse(json) as Student;
/// Object to Json(String)
JSON.stringify(any)

5. Http 的使用

使用官方提供的HTTP模塊

// 引入包名
import http from '@ohos.net.http';
import { BusinessError } from '@ohos.base';

// 每一個httpRequest對應一個HTTP請求任務(wù),不可復用
let httpRequest = http.createHttp();
// 用于訂閱HTTP響應頭贴见,此接口會比request請求先返回片部〉涤疲可以根據(jù)業(yè)務(wù)需要訂閱此消息
// 從API 8開始然爆,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)曾雕。 8+
httpRequest.on('headersReceive', (header) => {
  console.info('header: ' + JSON.stringify(header));
});
httpRequest.request(
  // 填寫HTTP請求的URL地址剖张,可以帶參數(shù)也可以不帶參數(shù)搔弄。URL地址需要開發(fā)者自定義。請求的參數(shù)可以在extraData中指定
  "EXAMPLE_URL",
  {
    method: http.RequestMethod.POST, // 可選倒庵,默認為http.RequestMethod.GET
    // 開發(fā)者根據(jù)自身業(yè)務(wù)需要添加header字段
    header: [{
      'Content-Type': 'application/json'
    }],
    // 當使用POST請求時此字段用于傳遞內(nèi)容
    extraData: "data to send",
    expectDataType: http.HttpDataType.STRING, // 可選擎宝,指定返回數(shù)據(jù)的類型
    usingCache: true, // 可選绍申,默認為true
    priority: 1, // 可選极阅,默認為1
    connectTimeout: 60000, // 可選筋搏,默認為60000ms
    readTimeout: 60000, // 可選,默認為60000ms
    usingProtocol: http.HttpProtocol.HTTP1_1, // 可選儒旬,協(xié)議類型默認值由系統(tǒng)自動指定
    usingProxy: false, //可選,默認不使用網(wǎng)絡(luò)代理竖般,自API 10開始支持該屬性
  }, (err: BusinessError, data: http.HttpResponse) => {
    if (!err) {
      // data.result為HTTP響應內(nèi)容涣雕,可根據(jù)業(yè)務(wù)需要進行解析
      console.info('Result:' + JSON.stringify(data.result));
      console.info('code:' + JSON.stringify(data.responseCode));
      // data.header為HTTP響應頭挣郭,可根據(jù)業(yè)務(wù)需要進行解析
      console.info('header:' + JSON.stringify(data.header));
      console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
      // 當該請求使用完畢時疗韵,調(diào)用destroy方法主動銷毀
      httpRequest.destroy();
    } else {
      console.error('error:' + JSON.stringify(err));
      // 取消訂閱HTTP響應頭事件
      httpRequest.off('headersReceive');
      // 當該請求使用完畢時流译,調(diào)用destroy方法主動銷毀
      httpRequest.destroy();
    }
  }
);

PS:后期小編會封裝一個簡化代碼的靜態(tài)庫提供使用

6. 路由的選擇與使用

路由提供兩種選擇方案:

組件 適用場景 特點 轉(zhuǎn)場動畫效果對比
Router 模塊間與模塊內(nèi)頁面切換 通過每個頁面的url實現(xiàn)模塊間解耦 頁面平推轉(zhuǎn)場效果
NavPathStack 模塊內(nèi)頁面切換 通過組件級路由統(tǒng)一路由管理 向右折疊轉(zhuǎn)場效果
  • Router的使用
router.pushUrl({
    url: 'pages/routerpage2',
    params: new routerParams('message' ,[123,456,789])
})

/// url 對應 resource - profile - mainpages.json
  • NavPathStack的使用

小編使用的方案是 NavPathStack 福澡,下面來重點說說使用方式革砸。

NavPathStack 是配合 Navigation 一起使用的算利,
Navigation導航組件做統(tǒng)一的頁面跳轉(zhuǎn)管理寇蚊,它提供了一系列屬性方法來設(shè)置頁面的標題欄、工具欄以及菜單欄的各種展示樣式仗岸。

//第一步允耿,需要在應用的根頁面自行維護 navStack 實例借笙,并傳遞給根節(jié)點 Navigation
@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack()

Navigation(this.pageInfos) {
  Column() {}
}
.title('NavIndex')
.navDestination(this.PageMap)


// 統(tǒng)一管理維護路由跳轉(zhuǎn)
@Builder
  PageMap(name: string) {
    if (name === 'pageOne') {
      PageOneTmp()
    } else if (name === 'pageTwo') {
      pageTwoTmp()
    }
}
// 第二步,注意较锡,目標跳轉(zhuǎn)頁面節(jié)點需要使用 NavDestination 進行包裹
// 目標跳轉(zhuǎn)頁面,例如 PageOneTmp
@Component
export struct PageOneTmp {
 build(){
    NavDestination(){
       Column(){
       
       }
    }
 }
}
/// 如何跳轉(zhuǎn)
this.pageInfos.pushPathByName('pageOne', null)

附注

Demo 示例已上傳:

GitHub:https://github.com/liyufengrex/HarmonyAtomicService

GitCode:https://gitcode.com/liyufengrex/HarmonyAtomicService

(基于API11開發(fā)业稼,支持NEXT及以上版本運行)已上傳可供參考,包含如下內(nèi)容:

  • 靜態(tài)庫+動態(tài)包+多模塊設(shè)計
  • 狀態(tài)管理
  • 統(tǒng)一路由管理(router+navPathStack)
  • 網(wǎng)絡(luò)請求蚂蕴、Loading 等工具庫封裝
  • 自定義組件低散、自定義彈窗(解耦)
  • EventBus 事件通知
  • 擴展修飾器骡楼,實現(xiàn) 節(jié)流熔号、防抖、權(quán)限申請
  • 動態(tài)路由 (navPathStack + 動態(tài)import + WrappedBuilder)
  • UI動態(tài)節(jié)點操作 (BuilderNode + NodeController)
  • 折疊屏適配示例
  • 組件工廠示例
  • 組件動態(tài)屬性設(shè)置示例
  • 云函數(shù)鸟整、云數(shù)據(jù)庫使用示例
  • 華為賬號服務(wù)示例(快速登陸引镊、快速驗證手機號)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市篮条,隨后出現(xiàn)的幾起案子弟头,更是在濱河造成了極大的恐慌,老刑警劉巖涉茧,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赴恨,死亡現(xiàn)場離奇詭異,居然都是意外死亡伴栓,警方通過查閱死者的電腦和手機伦连,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挣饥,“玉大人除师,你說我怎么就攤上這事∪臃悖” “怎么了汛聚?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長短荐。 經(jīng)常有香客問我倚舀,道長,這世上最難降的妖魔是什么忍宋? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任痕貌,我火速辦了婚禮,結(jié)果婚禮上糠排,老公的妹妹穿的比我還像新娘舵稠。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布哺徊。 她就那樣靜靜地躺著室琢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪落追。 梳的紋絲不亂的頭發(fā)上盈滴,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音轿钠,去河邊找鬼巢钓。 笑死,一個胖子當著我的面吹牛疗垛,可吹牛的內(nèi)容都是我干的症汹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼贷腕,長吁一口氣:“原來是場噩夢啊……” “哼烈菌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起花履,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挚赊,沒想到半個月后诡壁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡荠割,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年妹卿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔑鹦。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡夺克,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嚎朽,到底是詐尸還是另有隱情铺纽,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布哟忍,位于F島的核電站狡门,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏锅很。R本人自食惡果不足惜其馏,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爆安。 院中可真熱鬧叛复,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至抖僵,卻和暖如春鲤看,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耍群。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工义桂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蹈垢。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓慷吊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親曹抬。 傳聞我的和親對象是個殘疾皇子溉瓶,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容