HML、CSS、JavaScript在前面的章節(jié)中一直在用,現(xiàn)在就來專門介紹它們。
HML(HarmonyOS Markup Language)是一套類HTML的標(biāo)記語言,通過組件,事件構(gòu)建出頁面的內(nèi)容。頁面具備數(shù)據(jù)綁定、事件綁定、列表渲染、條件渲染和邏輯控制等高級能力。
關(guān)于頁面結(jié)構(gòu)我們這里就不再介紹了,前面我們一直在用組件構(gòu)建頁面。數(shù)據(jù)綁定我們也在前面章節(jié)中用到了很多次,現(xiàn)在我們就來看看。
1 數(shù)據(jù)綁定
通過在HML頁面中用雙大括號語法來聲明數(shù)據(jù),然后在JS文件中通過data對象進(jìn)行賦值,下面是典型示例
<!-- xxx.hml -->
<div onclick="changeText">
<text> {{content[1]}} </text>
</div>
// xxx.js
export default {
data: {
content: ['Hello World!', 'Welcome to my world!']
},
changeText: function() {
this.content.splice(1, 1, this.content[0]);
}
}
2 事件
通過‘on'或者‘@’將事件綁定在組件上,當(dāng)組件觸發(fā)事件時(shí)會(huì)執(zhí)行JS文件中對應(yīng)的事件處理函數(shù)。事件綁定的典型示例:
<!-- xxx.hml -->
<div class="container">
<text class="title">{{count}}</text>
<div class="box">
<!-- 沒有參數(shù)的事件處理函數(shù) -->
<input type="button" class="btn" value="increase" onclick="increase" />
<!-- 傳遞參數(shù) -->
<input type="button" class="btn" value="double" @click="multiply(2)" />
<input type="button" class="btn" value="square" @click="multiply(count)" />
</div>
</div>
// xxx.js
export default {
data: {
count: 0
},
increase() {
this.count++;
},
multiply(multiplier) {
this.count=multiplier * this.count;
}
};
HML組件還支持冒泡事件綁定。冒泡事件綁定包括:
典型示例如下:
<!-- xxx.hml -->
<div>
<!-- 使用事件冒泡模式綁定事件回調(diào)函數(shù)。5+ -->
<div on:touchstart.bubble="touchstartfunc"></div>
<div on:touchstart="touchstartfunc"></div>
<!-- 綁定事件回調(diào)函數(shù),但阻止事件向上傳遞。5+ -->
<div grab:touchstart.bubble="touchstartfunc"></div>
<div grab:touchstart="touchstartfunc"></div>
<!-- 使用事件冒泡模式綁定事件回調(diào)函數(shù)。6+ -->
<div on:click.bubble="clickfunc"></div>
<div on:click="clickfunc"></div>
<!-- 綁定事件回調(diào)函數(shù),但阻止事件向上傳遞。6+ -->
<div grab:click.bubble="clickfunc"></div>
<div grab:click="clickfunc"></div>
</div>
// xxx.js
export default {
clickfunc: function(e) {
console.log(e);
},
touchstartfuc: function(e) {
console.log(e);
},
}
Touch觸摸類事件支持捕獲,捕獲階段位于冒泡階段之前,捕獲事件先到達(dá)父組件然后達(dá)到子組件。
捕獲事件綁定包括:
示例如下:
<!-- xxx.hml -->
<div>
<!-- 使用事件捕獲模式綁定事件回調(diào)函數(shù)。5+ -->
<div on:touchstart.capture="touchstartfunc"></div>
<!-- 綁定事件回調(diào)函數(shù),但阻止事件向下傳遞。5+ -->
<div grab:touchstart.capture="touchstartfunc"></div>
</div>
// xxx.js
export default {
touchstartfuc: function(e) {
console.log(e);
},
}
3 列表渲染
在「華為鴻蒙應(yīng)用程序開發(fā) 12」JavaScript UI常用基礎(chǔ)組件Image這個(gè)章節(jié)中,我們顯示多張圖片時(shí)有用到列表渲染。列表渲染就是通過組件的for屬性,循環(huán)構(gòu)建組件,示例如下:
<!-- xxx.hml -->
<div class="array-container">
<!-- div列表渲染 -->
<!-- 默認(rèn)$item代表數(shù)組中的元素, $idx代表數(shù)組中的元素索引 -->
<div for="{{array}}" tid="id" onclick="changeText">
<text>{{$idx}}.{{$item.name}}</text>
</div>
<!-- 自定義元素變量名稱 -->
<div for="{{value in array}}" tid="id" onclick="changeText">
<text>{{$idx}}.{{value.name}}</text>
</div>
<!-- 自定義元素變量、索引名稱 -->
<div for="{{(index, value) in array}}" tid="id" onclick="changeText">
<text>{{index}}.{{value.name}}</text>
</div>
</div>
// xxx.js
export default {
data: {
array: [
{id: 1, name: 'jack', age: 18},
{id: 2, name: 'tony', age: 18},
],
},
changeText: function() {
if (this.array[1].name==="tony"){
this.array.splice(1, 1, {id:2, name: 'Isabella', age: 18});
} else {
this.array.splice(2, 1, {id:3, name: 'Bary', age: 18});
}
},
}
tid屬性主要用來加速for循環(huán)的重渲染,旨在列表中的數(shù)據(jù)有變更時(shí),提高重新渲染的效率。tid屬性是用來指定數(shù)組中每個(gè)元素的唯一標(biāo)識(shí),如果未指定,數(shù)組中每個(gè)元素的索引為該元素的唯一id。例如上述tid="id"表示數(shù)組中的每個(gè)元素的id屬性為該元素的唯一標(biāo)識(shí)。for循環(huán)支持的寫法如下:
說明
HML中的條件渲染分為2種:if/elif/else和show。兩種寫法的區(qū)別在于:第一種寫法里if為false時(shí),組件不會(huì)在vdom中構(gòu)建,也不會(huì)渲染,而第二種寫法里show為false時(shí)雖然也不渲染,但會(huì)在vdom中構(gòu)建;另外,當(dāng)使用if/elif/else寫法時(shí),節(jié)點(diǎn)必須是兄弟節(jié)點(diǎn),否則編譯無法通過。實(shí)例如下:
<!-- xxx.hml -->
<div class="container">
<button class="btn" type="capsule" value="toggleShow" onclick="toggleShow"></button>
<button class="btn" type="capsule" value="toggleDisplay" onclick="toggleDisplay"></button>
<text if="{{visible}}"> Hello-TV </text>
<text elif="{{display}}"> Hello-Wearable </text>
<text else> Hello-World </text>
</div>
/* xxx.css */
.container{
flex-direction: column;
align-items: center;
}
.btn{
width: 280px;
font-size: 26px;
margin: 10px 0;
}
// xxx.js
export default {
data: {
visible: false,
display: true,
},
toggleShow: function() {
this.visible=!this.visible;
},
toggleDisplay: function() {
this.display=!this.display;
}
}
渲染優(yōu)化:show方法。當(dāng)show為true時(shí),節(jié)點(diǎn)正常渲染;當(dāng)為false時(shí),僅僅設(shè)置display樣式為none。示例如下:
<!-- xxx.hml -->
<div class="container">
<button class="btn" type="capsule" value="toggle" onclick="toggle"></button>
<text show="{{visible}}" > Hello World </text>
</div>
/* xxx.css */
.container{
flex-direction: column;
align-items: center;
}
.btn{
width: 280px;
font-size: 26px;
margin: 10px 0;
}
// xxx.js
export default {
data: {
visible: false,
},
toggle: function() {
this.visible=!this.visible;
},
}
說明
禁止在同一個(gè)元素上同時(shí)設(shè)置for和if屬性
4 邏輯控制塊<block></block>
它使得循環(huán)渲染和條件渲染變得更加靈活;block在構(gòu)建時(shí)不會(huì)被當(dāng)作真實(shí)的節(jié)點(diǎn)編譯。注意block標(biāo)簽只支持for和if屬性。示例:
<!-- xxx.hml -->
<list>
<block for="">
<list-item type="students">
<text>{{$item.name}}</text>
</list-item>
<block for="$item.kinds">
<list-item type="kind">
<text>{{$item.age}}</text>
</list-item>
</block>
</block>
</list>
// xxx.js
export default {
data: {
glasses: [
{name:'sunglasses', kinds:[{name:'XXX',color:'XXX'},{name:'XXX',color:'XXX'}]},
{name:'nearsightedness mirror', kinds:[{name:'XXX',color:'XXX'}]},
],
},
}
5 模板引用
HML可以通過element引用模板文件,在自定義組件時(shí)會(huì)很有用。示例:
<!-- template.hml -->
<div class="item">
<text>Name: {{name}}</text>
<text>Age: {{age}}</text>
</div>
<!-- index.hml -->
<element name='comp' src='../../common/template.hml'></element>
<div>
<comp name="Tony" age="18"></comp>
</div>
CSS是描述HML頁面結(jié)構(gòu)的樣式語言。所有組件均存在系統(tǒng)默認(rèn)樣式,也可在頁面CSS樣式文件中對組件、頁面自定義不同的樣式。
1 尺寸單位
2 樣式導(dǎo)入
為了模塊化管理和代碼復(fù)用,CSS樣式文件支持 @import 語句,導(dǎo)入css文件。
3 聲明樣式
每個(gè)頁面目錄下存在一個(gè)與布局hml文件同名的css文件,用來描述該hml頁面中組件的樣式,決定組件應(yīng)該如何顯示。
(1)內(nèi)部樣式,支持使用style、class屬性來控制組件的樣式。例如:
<!-- index.hml -->
<div class="container">
<text style="color: red">Hello World</text>
</div>
/* index.css */
.container {
justify-content: center;
}
(2)文件導(dǎo)入,合并外部樣式文件。例如,在common目錄中定義樣式文件style.css,并在index.css文件首行中進(jìn)行導(dǎo)入:
/* style.css */
.title {
font-size: 50px;
}
/* index.css */
@import '../../common/style.css';
.container {
justify-content: center;
}
4 選擇器
css選擇器用于選擇需要添加樣式的元素,支持的選擇器如下表所示:
選擇器 | 樣例 | 樣例描述 |
.class | .container | 用于選擇class="container"的組件。 |
#id | #titleId | 用于選擇id="titleId"的組件。 |
tag | text | 用于選擇text組件。 |
, | .title, .content | 用于選擇class="title"和class="content"的組件。 |
#id .class tag | #containerId .content text | 非嚴(yán)格父子關(guān)系的后代選擇器,選擇具有id="containerId"作為祖先元素,class="content"作為次級祖先元素的所有text組件。如需使用嚴(yán)格的父子關(guān)系,可以使用“>”代替空格,如:#containerId>.content。 |
示例:
<!-- 頁面布局xxx.hml -->
<div id="containerId" class="container">
<text id="titleId" class="title">標(biāo)題</text>
<div class="content">
<text id="contentId">內(nèi)容</text>
</div>
</div>
/* 頁面樣式xxx.css */
/* 對所有div組件設(shè)置樣式 */
div {
flex-direction: column;
}
/* 對class="title"的組件設(shè)置樣式 */
.title {
font-size: 30px;
}
/* 對id="contentId"的組件設(shè)置樣式 */
#contentId {
font-size: 20px;
}
/* 對所有class="title"以及class="content"的組件都設(shè)置padding為5px */
.title, .content {
padding: 5px;
}
/* 對class="container"的組件下的所有text設(shè)置樣式 */
.container text {
color: #007dff;
}
/* 對class="container"的組件下的直接后代text設(shè)置樣式 */
.container > text {
color: #fa2a2d;
}
5 選擇器優(yōu)先級
選擇器的優(yōu)先級計(jì)算規(guī)則與w3c規(guī)則保持一致(只支持:內(nèi)聯(lián)樣式,id,class,tag,后代和直接后代),其中內(nèi)聯(lián)樣式為在元素style屬性中聲明的樣式。
當(dāng)多條選擇器聲明匹配到同一元素時(shí),各類選擇器優(yōu)先級由高到低順序?yàn)椋簝?nèi)聯(lián)樣式 > id > class > tag。
6 偽類
css偽類是選擇器中的關(guān)鍵字,用于指定要選擇元素的特殊狀態(tài)。例如,:disabled狀態(tài)可以用來設(shè)置元素的disabled屬性變?yōu)閠rue時(shí)的樣式。
除了單個(gè)偽類之外,還支持偽類的組合,例如,:focus:checked狀態(tài)可以用來設(shè)置元素的focus屬性和checked屬性同時(shí)為true時(shí)的樣式。支持的單個(gè)偽類如下表所示,按照優(yōu)先級降序排列:
名稱 | 支持組件 | 描述 |
:disabled | 支持disabled屬性的組件 | 表示disabled屬性變?yōu)閠rue時(shí)的元素(不支持動(dòng)畫樣式的設(shè)置)。 |
:focus | 支持focusable屬性的組件 | 表示獲取focus時(shí)的元素(不支持動(dòng)畫樣式的設(shè)置)。 |
:active | 支持click事件的組件 | 表示被用戶激活的元素,如:被用戶按下的按鈕、被激活的tab-bar頁簽(不支持動(dòng)畫樣式的設(shè)置)。 |
:waiting | button | 表示waiting屬性為true的元素(不支持動(dòng)畫樣式的設(shè)置)。 |
:checked | input[type="checkbox"、type="radio"]、 switch | 表示checked屬性為true的元素(不支持動(dòng)畫樣式的設(shè)置)。 |
:hover6+ | 支持mouseover事件的組件 | 表示鼠標(biāo)懸浮時(shí)的元素。 |
偽類示例如下,設(shè)置按鈕的:active偽類可以控制被用戶按下時(shí)的樣式:
<!-- index.hml -->
<div class="container">
<input type="button" class="button" value="Button"></input>
</div>
/* index.css */
.button:active {
background-color: #888888;/*按鈕被激活時(shí),背景顏色變?yōu)?888888 */
}
說明
針對彈窗類組件及其子元素不支持偽類效果,包括popup、dialog、menu、option、picker
7 樣式預(yù)編譯
預(yù)編譯提供了利用特有語法生成css的程序,可以提供變量、運(yùn)算等功能,令開發(fā)者更便捷地定義組件樣式,目前支持less、sass和scss的預(yù)編譯。使用樣式預(yù)編譯時(shí),需要將原css文件后綴改為less、sass或scss,如index.css改為index.less、index.sass或index.scss。
(1)當(dāng)前文件使用樣式預(yù)編譯,例如將原index.css改為index.less:
/* index.less */
/* 定義變量 */
@colorBackground: #000000;
.container {
background-color: @colorBackground; /* 使用當(dāng)前l(fā)ess文件中定義的變量 */
}
(2)引用預(yù)編譯文件,例如common中存在style.scss文件,將原index.css改為index.scss,并引入style.scss:
/* style.scss */
/* 定義變量 */
$colorBackground: #000000;
在index.scss中引用:
/* index.scss */
/* 引入外部scss文件 */
@import '../../common/style.scss';
.container {
background-color: $colorBackground; /* 使用style.scss中定義的變量 */
}
說明
引用的預(yù)編譯文件建議放在common目錄進(jìn)行管理。
8 CSS樣式繼承
css樣式繼承提供了子節(jié)點(diǎn)繼承父節(jié)點(diǎn)樣式的能力,繼承下來的樣式在多選擇器樣式匹配的場景下,優(yōu)先級排最低,當(dāng)前支持以下樣式的繼承:
JS文件用來定義HML頁面的業(yè)務(wù)邏輯,支持ECMA規(guī)范的JavaScript語言。基于JavaScript語言的動(dòng)態(tài)化能力,可以使應(yīng)用更加富有表現(xiàn)力,具備更加靈活的設(shè)計(jì)能力。下面講述JS文件的編譯和運(yùn)行的支持情況。
1 語法
支持ES6(EMACScript 6)語法。
使用import方法引入功能模塊:
import router from '@system.router';
使用import方法導(dǎo)入js代碼:
import utils from '../../common/utils.js';
2 對象
(1)應(yīng)用對象$def
使用this.$app.$def獲取在app.js中暴露的對象。
說明
應(yīng)用對象不支持?jǐn)?shù)據(jù)綁定,需主動(dòng)觸發(fā)UI更新。
示例代碼
// app.js
export default {
onCreate() {
console.info('AceApplication onCreate');
},
onDestroy() {
console.info('AceApplication onDestroy');
},
globalData: {
appData: 'appData',
appVersion: '2.0',
},
globalMethod() {
console.info('This is a global method!');
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;
},
invokeGlobalMethod() {
this.$app.$def.globalMethod();
},
getAppVersion() {
this.appVersion=this.$app.$def.globalData.appVersion;
}
}
(2)頁面對象
屬性 | 類型 | 描述 |
data | Object/Function | 頁面的數(shù)據(jù)模型,類型是對象或者函數(shù),如果類型是函數(shù),返回值必須是對象。屬性名不能以$或_開頭,不要使用保留字for, if, show, tid。 data與private和public不能重合使用。 |
$refs | Object | 持有注冊過ref 屬性的DOM元素或子組件實(shí)例的對象。示例見獲取DOM元素。 |
private | Object | 頁面的數(shù)據(jù)模型,private下的數(shù)據(jù)屬性只能由當(dāng)前頁面修改。 |
public | Object | 頁面的數(shù)據(jù)模型,public下的數(shù)據(jù)屬性的行為與data保持一致。 |
props | Array/Object | props用于組件之間的通信,可以通過<tag xxxx='value'>方式傳遞給組件;props名稱必須用小寫,不能以$或_開頭,不要使用保留字for, if, show, tid。目前props的數(shù)據(jù)類型不支持Function。示例見自定義組件。 |
computed | Object | 用于在讀取或設(shè)置進(jìn)行預(yù)先處理,計(jì)算屬性的結(jié)果會(huì)被緩存。計(jì)算屬性名不能以$或_開頭,不要使用保留字。示例見自定義組件。 |
其中data對象我們在前面章節(jié)的例子中用到過很多次。
3 方法
(1)數(shù)據(jù)方法
方法 | 參數(shù) | 描述 |
$set | key: string, value: any | 添加新的數(shù)據(jù)屬性或者修改已有數(shù)據(jù)屬性。 用法: this.$set('key',value):添加數(shù)據(jù)屬性。 |
$delete | key: string | 刪除數(shù)據(jù)屬性。 用法: this.$delete('key'):刪除數(shù)據(jù)屬性。 |
示例代碼:
// index.js
export default {
data: {
keyMap: {
OS: 'HarmonyOS',
Version: '2.0',
},
},
getAppVersion() {
this.$set('keyMap.Version', '3.0');
console.info("keyMap.Version=" + this.keyMap.Version); // keyMap.Version=3.0
this.$delete('keyMap');
console.info("keyMap.Version=" + this.keyMap); // log print: keyMap.Version=undefined
}
}
(2)公共方法
方法 | 參數(shù) | 描述 |
$element | id: string | 獲得指定id的組件對象,如果無指定id,則返回根組件對象。示例見獲取DOM元素。 用法: <div id='xxx'></div>
|
$rootElement | 無 | 獲取根組件對象。 用法:this.$rootElement().scrollTo({ duration: 500, position: 300 }), 頁面在500ms內(nèi)滾動(dòng)300px。 |
$root | 無 | 獲得頂級ViewModel實(shí)例。獲取ViewModel示例。 |
$parent | 無 | 獲得父級ViewModel實(shí)例。獲取ViewModel示例。 |
$child | id: string | 獲得指定id的子級自定義組件的ViewModel實(shí)例。獲取ViewModel示例。 用法: this.$child('xxx') :獲取id為xxx的子級自定義組件的ViewModel實(shí)例。 |
(3)事件方法
方法 | 參數(shù) | 描述 |
$watch | data: string, callback: string | Function | 觀察data中的屬性變化,如果屬性值改變,觸發(fā)綁定的事件。示例見自定義組件。 用法: this.$watch('key', callback) |
(4)頁面方法
方法 | 參數(shù) | 描述 |
scrollTo | scrollPageParam: ScrollPageParam | 將頁面滾動(dòng)到目標(biāo)位置,可以通過ID選擇器指定或者滾動(dòng)距離指定。 |
scrollPageParam有如下取值
名稱 | 類型 | 默認(rèn)值 | 描述 |
position | number | - | 指定滾動(dòng)位置。 |
id | string | - | 指定需要滾動(dòng)到的元素id。 |
duration | number | 300 | 指定滾動(dòng)時(shí)長,單位為毫秒。 |
timingFunction | string | ease | 指定滾動(dòng)動(dòng)畫曲線,可選值參考 animation-timing-function。 |
complete | ()=> void | - | 指定滾動(dòng)完成后需要執(zhí)行的回調(diào)函數(shù)。 |
示例:
this.$rootElement.scrollTo({position: 0});
this.$rootElement.scrollTo({
id: 'id',
duration: 200,
timingFunction: 'ease-in',
complete: ()=>void
});
(5)獲取DOM元素
<!-- index.hml -->
<div class="container">
<image-animator ref="animator" images="{{images}}"
duration="1s" onclick="handleClick">
</image-animator>
</div>
// index.js
export default {
data: {
images: [
{ src: '/common/frame1.png' },
{ src: '/common/frame2.png' },
{ src: '/common/frame3.png' },
],
},
handleClick() {
const animator=this.$refs.animator; // 獲取ref屬性為animator的DOM元素
const state=animator.getState();
if (state==='paused') {
animator.resume();
} else if (state==='stopped') {
animator.start();
} else {
animator.pause();
}
},
};
<!-- index.hml -->
<div class="container">
<image-animator class="image-player" id="animator"
images="{{images}}" duration="1s" onclick="handleClick">
</image-animator>
</div>
// index.js
export default {
data: {
images: [
{ src: '/common/frame1.png' },
{ src: '/common/frame2.png' },
{ src: '/common/frame3.png' },
],
},
handleClick() {
const animator=this.$element('animator'); // 獲取id屬性為animator的DOM元素
const state=animator.getState();
if (state==='paused') {
animator.resume();
} else if (state==='stopped') {
animator.start();
} else {
animator.pause();
}
},
};
(6)獲取ViewMode
根節(jié)點(diǎn)所在頁面:
<!-- root.hml -->
<element name='parentComp' src='../../common/component/parent/parent.hml'></element>
<div class="container">
<div class="container">
<text>{{text}}</text>
<parentComp></parentComp>
</div>
</div>
// root.js
export default {
data: {
text: 'I am root!',
},
自定義parent組件:
<!-- parent.hml -->
<element name='childComp' src='../child/child.hml'></element>
<div class="item" onclick="textClicked">
<text class="text-style" onclick="parentClicked">parent component click</text>
<text class="text-style" if="{{show}}">hello parent component!</text>
<childComp id="selfDefineChild"></childComp>
</div>
// parent.js
export default {
data: {
show: false,
text: 'I am parent component!',
},
parentClicked () {
this.show=!this.show;
console.info('parent component get parent text');
console.info(`${this.$parent().text}`);
console.info("parent component get child function");
console.info(`${this.$child('selfDefineChild').childClicked()}`);
},
}
自定義child組件:
<!-- child.hml -->
<div class="item" onclick="textClicked">
<text class="text-style" onclick="childClicked">child component clicked</text>
<text class="text-style" if="{{show}}">hello child component</text>
</div>
// child.js
export default {
data: {
show: false,
text: 'I am child component!',
},
childClicked () {
this.show=!this.show;
console.info('child component get parent text');
console.info('${this.$parent().text}');
console.info('child component get root text');
console.info('${this.$root().text}');
},
}
至此,關(guān)于華為鴻蒙應(yīng)用開發(fā)中HML、CSS、JavaScript語法部分的介紹就講完了,本章盡量用實(shí)例對每個(gè)知識(shí)點(diǎn)進(jìn)行了直觀地呈現(xiàn),大家可以先都熟悉下,然后在以后的開發(fā)中不記得的可以回過頭查看。
最后,老規(guī)矩,敲黑板:多動(dòng)手,多思考!代碼一定要親自動(dòng)手敲出來![呲牙][比心]
開始本章正式內(nèi)容之前先補(bǔ)充講一下前面章節(jié)沒有講到的一個(gè)小細(xì)節(jié)問題。
在我們每次關(guān)閉DevEco Studio不要直接點(diǎn)擊右上角的關(guān)閉按鈕,而是選擇菜單“文件 > 關(guān)閉項(xiàng)目”
這樣我們就回到了歡迎界面
當(dāng)我們下次啟動(dòng)程序的時(shí)候顯示的就是歡迎界面,而不是直接進(jìn)入上次編輯的項(xiàng)目界面。
本章目標(biāo):
了解華為鴻蒙應(yīng)用開發(fā)的JavaScript UI
啟動(dòng)DevEco Studio,打開我們在「鴻蒙開發(fā) 2」第一個(gè)華為鴻蒙(HarmonyOS)應(yīng)用程序(App)章節(jié)中創(chuàng)建的項(xiàng)目HelloWorld。
然后展開 pages 目錄下的兩個(gè)頁面對應(yīng)的目錄,我們可以看到每個(gè)頁面都包含了三個(gè)文件。
這就是JavaScript UI所包含的結(jié)構(gòu)(HML)、表現(xiàn)(CSS)和邏輯(JavaScript)共3個(gè)主要部分:
(1)HML:鴻蒙標(biāo)記語言(HarmonyOS Markup Language),用于定義用戶界面的結(jié)構(gòu)。通過HML編寫的界面結(jié)構(gòu)文件后綴名為.hml,因此HML既是一門語言,也是一種文件類型。要特別注意,雖然HML與HTML語法相似,但是仍然存在很多區(qū)別。
(2)CSS:層疊樣式表(Cascading Style Sheets),用于定義如何顯示HML組件。
(3)JavaScript:一種解釋性腳本語言,用于處理用戶界面的簡單業(yè)務(wù)邏輯,支持ECMAScript 6語法。
簡言之,就是HML用于構(gòu)建頁面,CSS用于美化頁面,JavaScript用于處理用戶與頁面的交互。
這里和Web開發(fā)的html,css,javascript很類似,但不完全一樣。
JavaScript UI支持手機(jī)(Phone)、平板(Tablet)、智慧屏(TV)或智能穿戴(Wearable)等設(shè)備的應(yīng)用開發(fā)。
我們在第2章中用于跳轉(zhuǎn)頁面時(shí)用到了JavaScript UI的router模塊
<!-- index.js -->
import router from '@system.router';
export default {
launch() {
router.push({
uri: 'pages/details/details'
})
}
}
router模塊主要包含以下方法:
(1)push(obj:IForwardPara):跳轉(zhuǎn)到另外一個(gè)頁面,而且原先的頁面仍然存在,只是被遮蓋而已。通過IForwardPara可以定義跳轉(zhuǎn)的頁面和傳遞的數(shù)據(jù),分別通過其URL屬性和params屬性定義。
(2)replace(obj:IForwardPara):跳轉(zhuǎn)到另外一個(gè)頁面,并銷毀當(dāng)前頁面。通過IForwardPara可以定義跳轉(zhuǎn)的頁面和傳遞的數(shù)據(jù),分別通過其URL屬性和params屬性定義。
(3)back(obj?:IBackPara):返回上一個(gè)頁面。通過IBackPara可以定義返回的頁面路徑(可選),通過該對象內(nèi)的path屬性定義。
(4)clear():清除被遮蓋的頁面,僅保留當(dāng)前顯示的頁面。
(5)getLength():獲取當(dāng)前頁面棧長度,即棧內(nèi)頁面數(shù)量。
(6)getState():獲取當(dāng)前頁面棧狀態(tài),返回IRouterState對象,該對象包括index、name和path共3個(gè)變量。index變量為整型,表示當(dāng)前頁面所在頁面棧的位置,從底層到頂層是從1開始計(jì)數(shù)的。name為字符串,表示當(dāng)前頁面文件名。path為字符串,表示當(dāng)前頁面的路徑。
還有我們在launch()方法中用router模塊的push方法調(diào)用的uri地址是哪里來的呢?
我們打開“Main > config.json”文件,定位到“js”字段
這是我們創(chuàng)建頁面時(shí)DecEco Studio為我們自動(dòng)添加的。
現(xiàn)在我們可以修改一下第二個(gè)頁面,添加一個(gè)按鈕,點(diǎn)擊按鈕后可以回到第一個(gè)頁面,以便更好地理解這些知識(shí)。
1 選擇“entry > src > main > js > default > pages >detail”,打開detail.hml文件,添加一個(gè)按鈕
<div class="container">
<text class="text">
Hi, I'm always here.
</text>
<!-- 添加一個(gè)按鈕 -->
<button class="button" type="capsule" value="Back" onclick="back"></button>
</div>
2 打開detail.css文件,添加按鈕的樣式
/* class選擇器,在hml文件中定義的class屬性,這里就是class="button" */
.button{
width: 240px;
height: 60px;
background-color: #007dff;
font-size: 30px;
text-color: white;
margin-top: 20px;
}
3 打開detail.js,實(shí)現(xiàn)返回第一個(gè)頁面的跳轉(zhuǎn)
// detail.js
import router from '@system.router';
export default {
back() {
router.push({
uri: 'pages/index/index' // 這里的地址是在config.json中已經(jīng)定義好的
});
}
}
注:其實(shí)這里我們可以直接使用router.back();就可以實(shí)現(xiàn)返回的功能了。
4 打開預(yù)覽器Previewer,點(diǎn)擊Back按鈕,我們可以看到功能已經(jīng)實(shí)現(xiàn)了。
篇目錄
本篇目錄
什么是HTML
HTML的作用
HTML發(fā)展史
IETF簡介
W3C簡介
網(wǎng)頁的固定格式
html標(biāo)簽
head標(biāo)簽
title標(biāo)簽
body標(biāo)簽
head內(nèi)部標(biāo)簽
meta標(biāo)簽
HTML標(biāo)簽
HTML標(biāo)簽分類
HTML標(biāo)簽關(guān)系分類
DTD文檔聲明
HTML和XHTML、HTML5區(qū)別
htm 和 .html擴(kuò)展名區(qū)別
什么是HTML
HTML其實(shí)是HyperText Markup Language的縮寫, 超文本標(biāo)記語言
HTML的作用
1.首先利用記事本保存了一個(gè)標(biāo)題和兩段描述, 然后修改純文本文件的擴(kuò)展名為.html, 然后再利用瀏覽器打開
2.打開之后發(fā)現(xiàn)顯示的格式不對, 不對的原因是因?yàn)樵诩兾谋疚募兴形淖侄际峭墑e的, 瀏覽器不知道哪些文字代表什么意思. 也就是瀏覽器不知道哪些文字是標(biāo)題, 哪些文字是段落…., 所以導(dǎo)致了顯示的格式不正確
正是因?yàn)槿绱? 所以HTML應(yīng)用而生. HTML就只有一個(gè)作用, 它是專門用來描述文本的語義的
. 也就是說我們可以利用HTML來告訴瀏覽器哪些是標(biāo)題, 哪些是段落.
這些用于描述其它文本語義的文本, 我們稱之為標(biāo)簽
. 并且這些用于描述文本語義的標(biāo)簽將來在瀏覽器中是不會(huì)被顯示出來
的
所以正是因?yàn)镠TML的這些標(biāo)簽是專門用來描述其它文本語義的, 并且在瀏覽器中不會(huì)被顯示出來, 所以我們稱這些文本為"超文本"
, 而這些文本又叫做標(biāo)簽
, 所以HTML被稱之為"超文本標(biāo)記語言"
注意事項(xiàng):
雖然我們利用H1標(biāo)簽描述一段文本之后, 這段文本在瀏覽器中顯示出來會(huì)被放大和加粗, 看上去我們是利用HTML的標(biāo)簽修改了被描述的那段文本的樣式. 但是一定要記住, HTML只有一個(gè)作用
, 它是專門用來給文本添加語義
的, 而不是用來修改文本的樣式的
H1標(biāo)簽它的作用是什么?
錯(cuò)誤: H1標(biāo)簽可以用來修改文字的大小, 并且還可以將文字加粗
正確: H1標(biāo)簽的作用是用來告訴瀏覽器, 哪些文字是標(biāo)題. 也就是H1標(biāo)簽是專門用于給指定的文字添加標(biāo)題語義
的
HTML發(fā)展史
IETF簡介
IETF是英文Internet Engineering Task Force的縮寫, 翻譯過來就是”互聯(lián)網(wǎng)工程任務(wù)組”
IETF負(fù)責(zé)定義并管理因特網(wǎng)技術(shù)的所有方面。包括用于數(shù)據(jù)傳輸?shù)腎P協(xié)議、讓域名與IP地址匹配的域名系統(tǒng)(DNS)、用于發(fā)送郵件的簡單郵件傳輸協(xié)議(SMTP)等
W3C簡介
W3C是英文World Wide Web Consortium的縮寫, 翻譯過來就是W3C理事會(huì)或萬維網(wǎng)聯(lián)盟, W3C是全球互聯(lián)網(wǎng)最具權(quán)威的技術(shù)標(biāo)準(zhǔn)化組織.
W3C于1994年10月在麻省理工學(xué)院計(jì)算機(jī)科學(xué)實(shí)驗(yàn)室成立。創(chuàng)建者是萬維網(wǎng)的發(fā)明者Tim Berners-Lee
W3C負(fù)責(zé)web方面標(biāo)準(zhǔn)的制定,像HTML、XHTML、CSS、XML的標(biāo)準(zhǔn)就是由W3C來定制的。
Tim Berners-Lee(蒂姆·伯納斯-李),萬維網(wǎng)之父、html設(shè)計(jì)者、w3c創(chuàng)始人
百度百科
網(wǎng)頁的固定格式
1.編寫網(wǎng)頁和寫信一樣都有一套規(guī)范和要求, 這套規(guī)范和要求中規(guī)定了寫信的固定格式
2.寫信基本結(jié)構(gòu)
3.編寫網(wǎng)頁的步驟:
3.1.新建一個(gè)文本文檔
3.2.利用記事本打開
3.3.編寫THML代碼
3.4.保存并且修改純文本文檔的擴(kuò)展名為.html
3.5.利用瀏覽器打開編寫好的文件
4.網(wǎng)頁基本結(jié)構(gòu):
5.通過觀察我們發(fā)現(xiàn), HTML基本結(jié)構(gòu)中所有的標(biāo)簽都是成對出現(xiàn)的, 這些成對出現(xiàn)的標(biāo)簽中有一個(gè)帶/有一個(gè)不帶/, 那么這些不帶/的標(biāo)簽我們稱之為開始標(biāo)簽, 這些帶/的我們稱之為結(jié)束標(biāo)簽html標(biāo)簽
作用:
用于告訴瀏覽器這是一個(gè)網(wǎng)頁, 也就是說告訴瀏覽器我是一個(gè)HTML文檔
注意點(diǎn):
其它所有的標(biāo)簽都必須寫在html標(biāo)簽里面, 也就是寫在html開始標(biāo)簽和結(jié)束標(biāo)簽中間
head標(biāo)簽
作用:
指定網(wǎng)站的標(biāo)題 / 指定網(wǎng)站的小圖片
添加網(wǎng)站的SEO相關(guān)的信息(指定網(wǎng)站的關(guān)鍵字/指定網(wǎng)站的描述信息)
外掛一些外部的css/js文件
添加一些瀏覽器適配相關(guān)的內(nèi)容
用于給網(wǎng)站添加一些配置信息
例如:
注意點(diǎn):
一般情況下, 寫在head標(biāo)簽內(nèi)部的內(nèi)容都不會(huì)顯示給用戶查看, 也就是說一般情況下寫在head標(biāo)簽內(nèi)部的內(nèi)容我們都看不到
title標(biāo)簽
作用:
專門用于指定網(wǎng)站的標(biāo)題, 并且這個(gè)指定的標(biāo)題將來還會(huì)作為用戶保存網(wǎng)站的默認(rèn)標(biāo)題
注意點(diǎn):
title標(biāo)簽必須寫在head標(biāo)簽里面
body標(biāo)簽
作用:
專門用于定義HTML文檔中需要顯示給用戶查看的內(nèi)容(文字/圖片/音頻/視頻)
注意點(diǎn):
雖然說有時(shí)候你可能將內(nèi)容寫到了別的地方在網(wǎng)頁中也能看到, 但是千萬不要這么干, 一定要將需要顯示的內(nèi)容寫在body中
一對html標(biāo)簽中(一個(gè)html開始標(biāo)簽和一個(gè)html結(jié)束標(biāo)簽)只能有一對body標(biāo)簽
head內(nèi)部標(biāo)簽
meta標(biāo)簽
1.為什么會(huì)有亂碼現(xiàn)象?
因?yàn)槲覀冊诰帉懢W(wǎng)頁的時(shí)候沒有指定字符集
2.如何解決亂碼現(xiàn)象?
在head標(biāo)簽中添加<meta charset="GBK" />
, 指定字符集
3.什么是字符集
字符集就是字符的集合, 也就是很多字符堆在一起. 其實(shí)字符集很像我們古代的”活字印刷術(shù)”, 在活字印刷術(shù)中就是將很多刻有漢字的小章放到一個(gè)盒子中, 然后需要印刷文字的時(shí)候再去盒子中取這個(gè)小章出來用, 正是因?yàn)槿绱? 所以導(dǎo)致了亂碼問題
假設(shè)北方人和南方人都擁有裝滿小章的盒子, 但是南方人和北方人在盒子中存儲(chǔ)小章的順序不太一樣, 那么這個(gè)時(shí)候如果北方人和南方人都需要去取”李”字, 在南方人記憶中李字在第6個(gè)盒子的第6行的第6列中(666), 在北方人的記憶中李字在第8個(gè)盒子的第8行的第8列中(888). 那么此時(shí)如果讓一個(gè)南方人去北方人的盒子中取”李”字的小章, 必然找不到,, 所以就導(dǎo)致了亂碼問題
這個(gè)地方北方人的存儲(chǔ)小章的盒子和南方人存儲(chǔ)小章的盒子就對應(yīng)網(wǎng)頁中指定的字符集, 在網(wǎng)頁中我們常見的字符集有兩個(gè)GBK/UTF-8, GBK就對應(yīng)北方人存儲(chǔ)的盒子, UTF-8就對應(yīng)南方人存儲(chǔ)的盒子
所以在網(wǎng)頁中指定字符集的意義就在于告訴瀏覽器我用的是哪個(gè)盒子, 你應(yīng)該如何去查找才能找到對應(yīng)的正確的內(nèi)容
4.GBK(GB2312)和UTF-8區(qū)別
提交比較大
體積比較小
GBK(GB2312)里面存儲(chǔ)的字符比較少, 僅僅存儲(chǔ)了漢字和一些常用外文
UTF-8里面存儲(chǔ)的世界上所有的文字
5.那么在企業(yè)開發(fā)中我們應(yīng)該使用GBK(GB2312)還是UTF-8呢?
如果你的網(wǎng)站僅僅包含中文, 那么推薦使用GB2312, 因?yàn)樗捏w積更小, 訪問速度更快
如果你的網(wǎng)站除了中文以外, 還包含了一些其它國家的語言 , 那么推薦使用UTF-8
懶人推薦: 不管三七二十一, 一律寫UTF-8即可
6.注意點(diǎn):
在HTML文件中指定的字符集必須和保存這個(gè)文件的字符集一致, 否則還是會(huì)出現(xiàn)亂碼
所以僅僅指定字符集不一定能解決亂碼問題, 還需要保存文件的時(shí)候, 文件的保存格式必須和指定的字符集一致才能保證沒有亂碼問題
HTML標(biāo)簽
HTML標(biāo)簽分類
單標(biāo)簽
只有開始標(biāo)簽沒有結(jié)束標(biāo)簽, 也就是由一個(gè)<>組成的
雙標(biāo)簽
有開始標(biāo)簽和結(jié)束標(biāo)簽, 也就是由一個(gè)<>和一個(gè)</>組成的
HTML標(biāo)簽關(guān)系分類
并列關(guān)系(兄弟/平級)
嵌套關(guān)系(父子/上下級)
DTD文檔聲明
什么是DTD文檔聲明?
由于HTML有很多個(gè)版本的規(guī)范, 每個(gè)版本的規(guī)范之間又有一定的差異. 所以為了讓瀏覽器能夠正確的編譯/解析/渲染我們的網(wǎng)頁, 我們需要在HTML文件的第一行告訴瀏覽器, 我們當(dāng)前這個(gè)網(wǎng)頁是用哪一個(gè)版本的HTML規(guī)范來編寫的
. 瀏覽器只要知道了我們是用哪一個(gè)版本的規(guī)范來編寫之后, 它就能夠正確的編譯/解析/渲染我們的網(wǎng)頁
DTD文檔聲明格式:
注意事項(xiàng):
不寫也能運(yùn)行
H5網(wǎng)頁里面用H4也能運(yùn)行
<!DOCTYPE>聲明
必須是 HTML 文檔的第一行,位于 <html> 標(biāo)簽之前
<!DOCTYPE> 聲明
不是 HTML 標(biāo)簽
<!DOCTYPE> 聲明
沒有結(jié)束標(biāo)簽
<!DOCTYPE> 聲明
對大小寫不敏感
這個(gè)聲明瀏覽器會(huì)看, 但是并不是完全依賴于這個(gè)聲明, 瀏覽器有一套自己的默認(rèn)的處理機(jī)制
HTML5之前
有2大種規(guī)范
, 每種規(guī)范中又有3小種規(guī)范
大規(guī)范 | 小規(guī)范 |
---|---|
HTML | Strict (嚴(yán)格的) |
HTML | Transitional(過度的,普通的,寬松的) |
HTML | Frameset(帶有框架的頁面) |
XHTML | Strict (嚴(yán)格的) |
XHTML | Transitional(過度的,普通的,寬松的) |
XHTML | Frameset(帶有框架的頁面) |
HTML的DTD文檔聲明和XHTML的DTD文檔聲明有何區(qū)別?
XHTML本身規(guī)定比如標(biāo)簽必須小寫、必須嚴(yán)格閉合、必須使用引號引起屬性等等, 而HTML會(huì)更加松散沒有這么嚴(yán)格
Strict表示嚴(yán)格的
, 這種模式里面的要求更為嚴(yán)格.這種嚴(yán)格主要體現(xiàn)在有一些標(biāo)簽不能使用
例如font標(biāo)簽/u標(biāo)簽等
font標(biāo)簽可以修改一個(gè)文本的字號、顏色、字體,但這和HTML的本質(zhì)有沖突,因?yàn)镠TML只能負(fù)責(zé)語義,不能負(fù)責(zé)樣式,而font標(biāo)簽是用于修改樣式的,所以在Strict中是不能使用font標(biāo)簽
u標(biāo)簽可以給一個(gè)文本加上下劃線,但這和HTML的本質(zhì)有沖突,因?yàn)镠TML只能負(fù)責(zé)語義,不能負(fù)責(zé)樣式,而u標(biāo)簽是用于添加下劃線是樣式.所以在Strict中是不能使用u標(biāo)簽
Transitional表示普通的
, 這種模式是沒有一些別的要求
例如可以使用font標(biāo)簽、u標(biāo)簽等
但是在企業(yè)開發(fā)中不會(huì)使用這些標(biāo)簽,因?yàn)檫@違背了HTML的本質(zhì), 而是將這些標(biāo)簽作為css的鉤子使用
Frameset表示框架
, 在框架的頁面使用
后面學(xué)到框架/NodeJS 再做詳細(xì)了解
常見的DOCTYPE有如下幾種
有這么多規(guī)范我們學(xué)習(xí)過程中到底使用哪一種比較合適呢?
www.baidu.com (B)
www.taobao.com (A)
www.qq.com (T)
www.sohu.com(大奇葩)
無論是HTML還是XHTML,過去
企業(yè)級開發(fā)中用的比較多的大部分都是Transitional類型
的文檔聲明
但是HTML5的時(shí)代已經(jīng)到來
,以上6中規(guī)范僅僅作為了解, 以后都用HTML5類型的文檔聲明
, HTML5向下兼容(求此刻WC3心里陰影面積)
目前國內(nèi)一線網(wǎng)站都更新到了HTML5的文檔聲明, 所以后續(xù)授課也是全程使用HTML5的文檔聲明
HTML和XHTML、HTML5區(qū)別
在HTML的早期發(fā)展中,大部分標(biāo)準(zhǔn)都是所謂的retro-spec,即先有實(shí)現(xiàn)后有標(biāo)準(zhǔn)
。在這種情況下,HTML標(biāo)準(zhǔn)不是很規(guī)范
,瀏覽器也對HTML頁面中的錯(cuò)誤相當(dāng)寬容
。這反過來又導(dǎo)致了HTML開發(fā)者寫出了大量含有錯(cuò)誤的HTML頁面
html語言本身有一些缺陷
(例如: 內(nèi)容和形式不能分離;標(biāo)簽單一;數(shù)據(jù)不能復(fù)用等等),隨著xml的興起人們希望xml來彌補(bǔ)html的不足
,但是目前有成千上萬的網(wǎng)頁都是用html編寫的,所以完全使用xml來替代html還為時(shí)過早
,于是W3C在2000年推出了xhtml1.0, 建立xhtml的目的就是實(shí)現(xiàn)從html向xml的過度
為了規(guī)范HTML
,W3C結(jié)合XML制定了XHTML 1.0標(biāo)準(zhǔn)
,這個(gè)標(biāo)準(zhǔn)沒有增加任何新的標(biāo)簽,只是按照XML的要求來規(guī)范HTML,并定義了一個(gè)新的MIME type application/xhtml+xml。W3C的初衷
是要求瀏覽器對這個(gè)MIME type實(shí)行強(qiáng)錯(cuò)誤檢查
,如果頁面有HTML錯(cuò)誤,就要顯示錯(cuò)誤信息
。但是由于已有的web頁面中已經(jīng)有了大量的錯(cuò)誤,很多開發(fā)者拒絕使用新的MIME type
。W3C不得已
,在XHTML 1.0的標(biāo)準(zhǔn)之后增加了一個(gè)附錄C
,允許
開發(fā)者使用XHTML語法來寫頁面,同時(shí)使用舊的MIME type,application/html
,來分發(fā)頁面
W3C隨后在XHTML 1.1中取消了附錄C
,即使用XHTML 1.1標(biāo)準(zhǔn)的頁面必須用新的MIME type來分發(fā)。于是這個(gè)標(biāo)準(zhǔn)并沒有很多人采用
有了XHTML的教訓(xùn),W3C在制定下一代HTML標(biāo)準(zhǔn)時(shí)(HTML5),就將向后兼容作為了一個(gè)很重要的原則
。HTML5確實(shí)引入了許多新的特性,但是它最重要的一個(gè)特性是,不會(huì)break已有的網(wǎng)頁
。你可以將任何已有的網(wǎng)頁的第一行改成<!DOCTYPE html>,它就成也一個(gè)HTML5頁面
,并且可以照樣在瀏覽器里正常的展示。
簡而言之
HTML語法非常寬松容錯(cuò)性強(qiáng);
XHTML更為嚴(yán)格,它要求標(biāo)簽必須小寫、必須嚴(yán)格閉合、標(biāo)簽中的屬性必須使用引號引起等等;
HTML5是HTML的下一個(gè)版本所以除了非常寬松容錯(cuò)性強(qiáng)以外,還增加許多新的特性
.htm 和 .html擴(kuò)展名區(qū)別
DOS操作系統(tǒng)(win95或win98)下只能支持長度為3的后綴名
,所以是htm
但在windows后綴長度可以大于3位,所以windows下無所謂htm與html,html是為長文件的格式命名的
所以htm是為了兼容過去的DOS命名格式存在的
關(guān)于課程的疑問和討論,可以登錄http://bbs.520it.com/forum.php?mod=viewthread&tid=2423。
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。