初窺鴻蒙

一、什麼是鴻蒙

鴻蒙即 HarmonyOS ,是華爲公司推出的支持手機、平板、智能穿戴、智慧屏、車機等多種終端設備的分佈式操作系統,並且它提供了多語言開發的 API,支持 Java、XML、C/C++、JS、CSS、HML(類 html 的鴻蒙自己的標記語言)等開發語言,而且它提供多種響應式佈局方案,支持柵格化佈局,可以使用同一套代碼部署在手機手錶平板等多種不同尺寸屏幕的設備上。

二、開發準備

2.1 環境安裝

開發鴻蒙軟件需要用到 HUAWEI DevEco Studio,它提供了模板創建、開發、編譯、調試、發佈等服務。

1、登錄 HarmonysOS 應用開發門戶,點擊右上角註冊按鈕,註冊開發者帳號。

2、進入 HUAWEI DevEco Studio 產品頁,登錄華爲開發者賬號後下載 DevEco Studio 安裝包並進行安裝。

3、啓動 DevEco Studio,根據工具引導下載 HarmonyOS SDK。 下載HarmonyOS SDK

4、下載 HarmonyOS SDK 成功後會進入歡迎頁,點擊歡迎頁中的 Configure > Settings 打開設置窗口,點擊 Apparance&behavior > System settings > HarmonyOS SDK,選中 JS SDK 進行下載。 下載JS SDK

至此開發環境安裝完成。

2.2 新建項目

點擊菜單欄中的 File > New > New Project 新建項目 選擇需要開發的項目設備,然後選擇 Empty Featrue Ability(JS) 後,點擊 Next,此時會出現項目的信息配置 項目信息配置 點擊 Finish,一個新的項目就被創建出來了。

2.3 項目目錄

項目目錄

使用 JS SDK 進行開發的話,需要關注的是 entry > src > main > js 文件夾,其中:

  • i18n 目錄下存放的是多語言的 json 文件

    en-US.json 爲英文模式展示的內容 zh-CN.json 爲中文模式展示的內容

  • pages 下存放的是項目的多個頁面,每個頁面都由 hml、js 和 css 組成

    hml 文件定義了頁面的佈局、頁面中用到的組件,以及這些組件的層級關係 js 文件定義了頁面的業務邏輯,比如數據綁定、事件處理等 css 文件定義了 index 頁面的樣式

  • app.js 中存放的是全局的 js 邏輯和 app 的生命週期管理

除此之外,還可以自己創建 common 目錄用於存放公共資源文件,比如:公共樣式和公用方法。

2.4 生命週期

生命週期分爲應用的生命週期以及頁面的生命週期

生命週期

其中,應用的生命週期主要分爲應用創建時調用的 onCreate,以及應用銷燬時觸發的 onDestroy。

而頁面的生命週期分爲:

  • onInit:頁面數據準備完成時觸發;
  • onReady:頁面編譯完成時觸發;
  • onShow:頁面展示時觸發;
  • onHide:頁面被隱藏時觸發;
  • onDestroy:頁面被銷燬時觸發;

由於JS UI只支持應用同時運行並展示一個頁面,因此當應用從頁面 A 跳轉到頁面 B 時,首先觸發頁面 A 的 onHide、onDestroy 函數,然後依次調用頁面 B 的 onInit、onReady、onShow 函數來初始化和顯示頁面 B。

三、組件

在 hml 文件中,組件分爲容器組件、基礎組件、媒體組件、畫布組件、柵格組件,由於篇幅有限,這裏只列舉一下組件名稱和對應的描述,感興趣的同學可以點擊 組件文檔 進行查閱。

3.1 容器組件

組件名 描述
div 基礎容器
list 列表容器
list-item list 的子組件,用來展示列表具體 item
list-item-group list 的子組件,用來展示分組,寬度默認充滿 list 組件
badge 新事件標記容器
dialog 自定義彈窗容器
panel 彈出式可滑動面板容器
popup 氣泡提示容器
refresh 下拉刷新容器
stack 堆疊容器,子組件按照順序依次入棧,後一個子組件覆蓋前一個子組件
stepper 步驟導航器。當完成一個任務需要多個步驟時,可以使用步驟導航器展示當前進展
stepper-item 步驟導航器子組件,作爲步驟導航器某一個步驟的內容展示組件
swiper 滑動切換容器
tabs tab 頁標籤切換容器
tab-bar tabs 的子組件,用來展示 tab 的標籤區
tab-content tabs 的子組件,用來展示 tab 的內容區

3.2 基礎組件

組件名 描述
image 圖片組件,用來渲染展示圖片
image-animator 圖片幀動畫播放器
text 文本組件,用於展示文本信息
span text 的子組件,提供文本修飾能力
textarea 多行文本輸入框
input 交互式組件,包括單選框,多選框,按鈕和單行文本輸入框
button 按鈕組件,包括膠囊按鈕、圓形按鈕、文本按鈕、弧形按鈕、下載按鈕
chart 圖表組件,用於呈現線形圖、柱狀圖、量規圖界面
divider 提供分隔器組件,分隔不同內容塊/內容元素。可用於列表或界面佈局
label 爲 input、button、textarea 組件定義相應的標註,點擊該標註時會觸發綁定組件的點擊效果
marquee 跑馬燈組件,用於展示一段單行滾動的文字
menu 菜單組件,作爲臨時性彈出窗口,用於展示用戶可執行的操作
select 下拉選擇組件,可讓用戶在多個選項之間選擇
option 可作爲 menu 或 select 組件的子組件,用來展示具體項目
picker 滑動選擇器組件,類型支持普通選擇器,日期選擇器,時間選擇器,時間日期選擇器,多列文本選擇器
picker-view 嵌入頁面的滑動選擇器
piece 一種塊狀的入口組件,可包含圖片和文本,常用於展示收件人
progress 進度條組件,用於顯示內容加載或操作處理進度
qrcode 二維碼組件,用於生成並顯示二維碼
rating 評分條組件
search 搜索框組件,用於提供用戶搜索內容的輸入區域
slider 滑動條組件,用來快速調節設置值,如音量、亮度等
switch 開關組件,用於開啓或關閉某個功能
toolbar 工具欄組件,放在界面底部,用於展示針對當前界面的操作選項
toolbar-item toolbar 子組件,用於展示工具欄上的一個操作選項
toggle 狀態按鈕組件,用於從一組選項中進行選擇

3.3 媒體組件

媒體組件暫時只有 video 組件一個,除了智能穿戴設備不支持外,手機、平板、智慧屏設備均支持該組件,它爲設備提供了視頻播放功能。

3.4 畫布組件

畫布組件展示只有 canvas 組件一個,手機、平板、智慧屏、智能穿戴設備均支持該組件,它爲設備提供了自定義繪製圖形的能力。

3.5 柵格組件

組件名 描述
grid-container 柵格佈局容器根節點
grid-row grid-row 是柵格佈局容器 grid-container 的子容器組件,使用 flex 橫向佈局,排列每個 grid-col 容器,justify-content 與 align-items 默認爲 flex-start,支持折行顯示
grid-col grid-row 的子容器組件

柵格系統有 Margins, Gutters, Columns 三個屬性:

  • Margins:用於控制元素距離屏幕最邊緣的距離
  • Gutters:用來控制元素和元素之間的距離關係
  • Columns:用來輔助佈局的主要定位工具,不同的屏幕尺寸匹配不同的 Columns 數量來輔助佈局定位,它會根據實際設備的寬度和 Columns 數量自動計算每一個 Columns 的寬度

柵格系統

不同的設備根據水平寬度 px,顯示不同數量的柵格數:

xs : 0px < 水平分辨率 < 320px:2 Columns 柵格;

sm : 320px <= 水平分辨率 < 600px:4 Columns 柵格;

md : 600px <= 水平分辨率 < 840px:8 Columns 柵格;

lg : 840px <= 水平分辨率:12 Columns 柵格。

四、HML語法

HML(HarmonyOS Markup Language)是一套類 HTML 的標記語言,通過組件,事件構建出頁面的內容。頁面具備事件綁定、數據綁定、列表渲染、條件渲染和邏輯控制等能力。

4.1 事件綁定

hml 中事件綁定默認返回一個事件對象參數,可以通過該參數獲取事件信息,同時也可以傳遞額外參數。

<!-- xxx.hml -->
<div>
  <!-- 正常格式 -->
  <div onclick="clickfunc"></div>
  <!-- 縮寫 -->
  <div @click="clickfunc('hello')"></div>
  <!-- 使用事件冒泡模式綁定事件回調函數 -->
  <div on:touchstart.bubble="touchstartfunc"></div>
  <!-- 使用事件捕獲模式綁定事件回調函數 -->
  <div on:touchstart.capture="touchstartfunc"></div>
  <!-- on:{event}等價於on:{event}.bubble -->
  <div on:touchstart="touchstartfunc"></div>
  <!-- 綁定事件回調函數,但阻止事件向上傳遞 -->
  <div grab:touchstart.bubble="touchstartfunc"></div>
  <!-- 綁定事件回調函數,但阻止事件向下傳遞 -->
  <div grab:touchstart.capture="touchstartfunc"></div>
  <!-- grab:{event}等價於grab:{event}.bubble -->
  <div grab:touchstart="touchstartfunc"></div>
</div>
// xxx.js
export default {
  data: {
    text: '',
  },
  clickfunc: function(str, e) {
    console.log(e);
    this.text = str;
  },
  touchstartfunc: function(e) {
    console.log(e);
  }
}

4.2 數據綁定

數據綁定的形式分兩種:數據初始化,數據更新 數據更新流程

hml 只支持數據層到視圖層的單向數據綁定。 視圖層想改變數據層,只能通過綁定事件的方式實現。

4.2.1 數據初始化

hml 中的數據都來自於對應 js 中的 data 對象,因此在初始化頁面時,在 data 對象中寫入數據,hml 中就可以通過 {{}} 的形式綁定數據。

// xxx.js
export default {
  data: {
    text: 'HELLO WORLD'
  }
}
<!-- xxx.hml -->
<div>{{text}}</div>

4.2.2 數據更新

通過爲頁面元素綁定事件,可以調用方法更新數據,從而觸發視圖更新數據

// xxx.js
export default {
  data: {
    text: 'HELLO WORLD'
  },
  changeText: function() {
    this.$set('text', '你好,世界');
  }
}
<!-- xxx.hml -->
<div @click='changeText'>{{text}}</div>

4.3 列表渲染

hml 中需要進行列表渲染的話只需在組件上添加 for 屬性並綁定需要渲染的數據,同時可自定義變量和索引的名稱:

// xxx.js
export default {
  data: {
    array: [
      {id: 1, name: '老周', age: 28}, 
      {id: 2, name: '老李', age: 29},
    ],
  },
  changeText: function(val, index) {
    if (val === "老李"){
      this.array.splice(index, 1, {id:2, name: '老王', age: 30});
    } else {
      this.array.splice(index, 1, {id:3, name: '老鄭', age: 31});
    }
  },
}
<!-- xxx.hml -->
<div class="array-container">
  <!-- div列表渲染 -->
  <!-- 默認$item代表數組中的元素, $idx代表數組中的元素索引 -->
  <div for="{{array}}" tid="id" onclick="changeText($item.name, $idx)">
    <text>{{$idx}}.{{$item.name}}</text>
  </div>
  <!-- 自定義元素變量名稱 -->
  <div for="{{value in array}}" tid="id" onclick="changeText(value.name, $idx)">    
    <text>{{$idx}}.{{value.name}}</text>
  </div>
  <!-- 自定義元素變量、索引名稱 -->
  <div for="{{(index, value) in array}}" tid="id" onclick="changeText(value.name, index)">    
    <text>{{index}}.{{value.name}}</text>
  </div>
</div>

數組中的每個元素必須存在 tid 指定的數據屬性,且必須具有唯一性。 針對數組內的數據修改,請使用 splice 方法生效數據綁定變更

4.4 條件渲染

hml 中實現條件渲染有兩種方式,分別是爲組件添加 if/elif/else 或 show 屬性,它們的區別在於 if/elif/else 屬性不符合條件判斷則不會在 vdom 中構建,而 show 屬性爲 false 時雖然不會渲染,但是會在 vdom 中構建,只是設置了 display 樣式爲 none。

因此出於性能因素考慮,顯示隱藏狀態需要頻繁切換推薦使用 show,顯示狀態改變次數較少則使用 if/elif/else。

// xxx.js
export default {
  data: {
    show: false,
    display: true,
    visible: false
  },
  toggle: function() {
    this.visible = !this.visible;
  }
}
<!-- xxx.hml -->
<div class="container">
  <text if="{{show}}"> 你好,世界 </text>
  <text elif="{{display}}"> hi </text>
  <text else> Hello World </text>
  
  <button class="btn" type="capsule" value="toggle" onclick="toggle"></button>
  <text show="{{visible}}" > Hello World! </text>
</div>

當使用 if/elif/else 寫法時,節點必須是兄弟節點,否則編譯無法通過 禁止在同一個元素上同時設置 for 和 if 屬性

4.5 邏輯控制塊

hml 中提供了 <block> 控制塊,它不會被當作真實的節點編譯,但是隻支持 for 和 if 屬性。

4.6 自定義組件

HML 可以通過 element 標籤引用模板文件,通過它可以實現自定義組件。

<!-- template.hml -->
<div class="item"> 
  <text>Name: {{name}}</text>
  <text>Age: {{age}}</text>
</div>
<!-- index.hml -->
<element name='man' src='../../common/template.hml'></element>
<div>
  <man name="老朱" age="28"></man>
</div>

其中 element 標籤的 name 屬性則爲自定義組件的名稱,src 屬性爲自定義組件相對該文件的路徑,可以爲自定義組件標籤添加屬性向其傳遞數據,自定義組件內也可使用 $emit 方法向父組件傳遞參數。

五、JS語法

鴻蒙中的 js 文件支持 ES6 語法。

5.1 引用

鴻蒙中可以使用 import 方法引入功能模塊或 js 代碼:

import router from '@system.router'
import utils from '../../common/utils.js'

5.2 獲取app對象

在頁面中可以使用 this.$app.$def 獲取在 app.js 中暴露的對象。

// app.js
export default {
  onCreate() {
    console.info('App onCreate');
  },
  onDestroy() {
    console.info('App onDestroy');
  },
  globalData: {
    appData: 'appData',
    appVersion: '2.0',
  },
  changeAppVer () {
    this.globalData.appVersion = '3.0';
  }
};
// index.js
export default {
  data: {
    appData: 'localData',
    appVersion:'1.0',
  },
  onInit() {
    this.appData = this.$app.$def.globalData.appData;
    this.appVersion = this.$app.$def.globalData.appVersion;
  },
  pageMethod() {
    this.$app.$def.changeAppVer();
  }
}

5.3 頁面對象

屬性 類型 描述
data Object/Function 頁面的數據模型
$refs Object 持有註冊過 ref 屬性的 DOM 元素或子組件實例的對象
props Array/Object props 用於接收父組件傳遞過來的參數
computed Object 計算屬性,用於在讀取或設置進行預先處理,計算屬性的結果會被緩存
private Object 頁面的數據模型,private 下的數據屬性只能由當前頁面修改
public Object 頁面的數據模型,public 下的數據屬性的行爲與 data 保持一致

5.4 方法

5.4.1 數據方法

屬性 類型 參數 描述
$set Function key: string, value: any 添加新的數據屬性或者修改已有數據屬性。用法:this.$set('key',value)。
$delete Function key: string 刪除數據屬性。用法:this.$delete('key')。
export default {
  data: {
    appInfo: {
      OS: 'HarmonyOS',
      Version: '2.0',
    },
  },
  changeAppInfo() {
    this.$set('appInfo.Version', '3.0');
    console.log(this.appInfo);
    this.$delete('appInfo');
    console.log(this.appInfo);
  }
}

5.4.2 事件方法

鴻蒙中可以使用 $watch 方法觀察 data 中的屬性變化,如果屬性值改變,則會觸發綁定的事件。

export default { 
  props: ['title'],
  onInit() {
    this.$watch('title', 'onPropChange');
  },
  onPropChange(newV, oldV) {
    console.info('title屬性由'+ oldV +'變化爲' + newV);
  },
}

5.5 路由

{
  "pages": [
    "pages/index/index",
    "pages/detail/index"
  ]
}

鴻蒙 app 中頁面的路由信息保存在 src > main > config.json 文件中的 pages 內,引入 @system.router 後,調用其 push 方法傳入需要跳轉頁面的 uri,即可完成跳轉,也可使用其 back 方法回到首頁。

import router from '@system.router';
export default {
  launch() {
    router.push ({
      uri: 'pages/detail/index',
    });
  },
  goBack() {
    router.back();
  }
}

六、CSS語法

CSS 是描述 HML 頁面結構的樣式語言,所有組件均存在系統默認樣式,也可在頁面 CSS 樣式文件中對組件、頁面自定義不同的樣式。

6.1 尺寸單位

鴻蒙中尺寸單位有兩種,px(邏輯像素) 以及百分比。

{
  "window": {
    "designWidth": 720,
    "autoDesignWidth": false
  }
}

邏輯像素的配置在 src > main > config.json 文件中的 window 內,designWidth 爲屏幕的邏輯寬度,默認爲720px,實際顯示時會將頁面佈局縮放至屏幕實際寬度,如100px在實際寬度爲1440物理像素的屏幕上,實際渲染爲200物理像素。

當 autoDesignWidth 設置爲 true 時,邏輯像素 px 將按照屏幕密度進行縮放,如 100px 在屏幕密度爲3的設備上,實際渲染爲300物理像素。

而百分比單位表示該組件佔父組件尺寸的百分比,如組件的 width 設置爲50%,代表其寬度爲父組件的50%。

6.2 樣式導入

CSS 樣式文件支持 @import 語句,導入 CSS 文件。

@import '../../common/style.css';

七、總結

使用鴻蒙的 JS SDK 開發 App,整體的項目結構、生命週期以及開發流程很像微信的小程序,而 hml 和 JS 的語法又很像 Vue,整個流程走下來,感覺對 web 開發者而言還是很友好的,相信有 Web 前端開發基礎的小夥伴們都可以快速的上手。

由於篇幅有限,文中還有很多沒有提到的鴻蒙賦予開發者的硬件調用能力,希望鴻蒙可以越做越好,讓越來越多的開發者和用戶加入到鴻蒙的大生態中來。

八、參考


歡迎關注凹凸實驗室博客:aotu.io

或者關注凹凸實驗室公衆號(AOTULabs),不定時推送文章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章