鸿蒙安装文件的位置以及文件夹的名称不能有中文、空格和其他特殊字符,全部使用英文字母。
-
- 准备安装目录
安装文件所需要的磁盘剩余空间保证大于40G及以上。例如:在D盘创建文件件hongmeng:D:\hongmeng空文件夹。
-
- 解压缩devecostudio-windows-3.1.0.500.zip文件
双击安装文件deveco-studio-3.1.0.500.exe进入安装

需要修改安装目录到自己建立的文件夹





基础安装完成。
-
- 创建项目
1.3.1.创建项目,并为项目准备SDK环境


进入开发界面





1.3.2.查看配置信息


选择安装SDK3.0 API7版本
1.3.3.创建鸿蒙项目




1.3.4.创建模拟器运行项目
1.预示效果

- 建立手机模拟器





新建模拟器


开始下载模拟器




点击运行图标,运行模拟器


1.4.鸿蒙项目的目录结构

1.5.使用设计器设计视图(低代码构建)



将视图设计界面转为eTS代码


点击convert以后,提示转换成。


通过视图生成的代码
@Entry
@Component
struct Listproduct {
@State message: string = 'Hello World'
@Builder navigation1Title_Glvb() {
Text("首页")
.width("44.68vp")
.height("31.02vp")
}
aboutToAppear() {
}
build() {
Column() {
Column() {
Navigation() {
Image($r('app.media.lazi'))
.width("349.96vp")
.height("200vp")
Divider()
.width("100%")
.height("10vp")
.margin({ top: "5vp", bottom: "5vp", left: "5vp", right: "5vp" })
.color("#4be811")
.strokeWidth("10vp")
Grid() {
GridItem() {
Image($r('app.media.lazi'))
.width("66.29vp")
.height("52.54vp")
}
.width("50vp")
.height("50vp")
}
.width("100%")
.height("100vp")
List() {
ListItem()
.width("100%")
.height("58.74vp")
ListItem()
.width("100%")
.height("58.74vp")
ListItem()
.width("100%")
.height("58.74vp")
ListItem()
.width("100%")
.height("58.74vp")
ListItem()
.width("100%")
.height("58.74vp")
}
.width("357.46vp")
.height("322.43vp")
}
.width("100%")
.height("100%")
.offset({ x: "0vp", y: "0vp" })
.title(this.navigation1Title_Glvb)
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
.width("100%")
.height("100%")
}
}
|
理解javascript代码:
<html>
<head>
<title>我的页面</title>
<script>
function dochengMessage(){
//获取文本框的值
var msgtxt=document.getElementById("message").value;
document.getElementById("mydiv").innerHTML=msgtxt;
}
function doDate(){
var date=new Date();
var sdate=date.toLocaleString();
document.getElementById("sdate").innerHTML=sdate;
window.setTimeout("doDate()",1000);
}
</script>
</head>
<body onload="doDate()">
<div id="sdate">
</div>
<div id="mydiv" style="font-size='36px'">
你好世界
</div>
<p>
请输入信息: <input type="text" name="message" id="message">
<input type="button" value="确定" onclick="dochengMessage()">
</p>
</body>
</html> |

-
- TypeScript简介
TypeScript 是一种由微软开发的自由和开源的编程语言,它是 JavaScript 的一个超集。
◼ TypeScript本质上是添加了可选的静态类型和基于类的面向对象编程。
◼ TypeScript可以在任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。
◼ TypeScript 扩展了 JavaScript 的语法,所以任何现有的 JavaScript 程序可以不加改变的在 TypeScript 下工作。

-
- Typescript演练场(编码的网站)
◼ TypeScript 官方提供了一个在线运行环境,可以用来学习 TypeScript 相关知识与不同版本的功能特性。
◼ 进入官网首页(https://www.typescriptlang.org/)点击“Playground”即可进入演练场。
编写一下代码:
function getName(name:string){
return "您好,"+name;
}
let sname="张飞";
console.log(getName(sname))
|

课堂练习:
- 创建ets鸿蒙项目,使用设计器编写界面,熟悉各个组件。
- 仿照课堂案例,熟悉js代码的编写规范和函数的定义方式。
- 使用https://www.typescriptlang.org/play/网站提供的ts编辑器,编写简单的ts代码,并输出测试的结果。
-
- ets项目的结构描述
2.3.1.文件类型
.ets结尾的eTS(extended TypeScript)文件,用于描述UI布局、样式、 事件交互和页面逻辑。
2.3.2.文件及目录
➢ app.ets文件用于全局应用逻辑和应用生命周期管理。
➢ pages目录用于存放所有组件页面。 ets文件存放于此目录
➢ common目录用于存放公共代码文件。
➢ resources目录用于存放资源配置文件。
2.3.3.config.json中js标签配置
开发框架需要应用的config.json中配置相关的js标签,其中包含了实例名称、页面路由、视图窗口配置信息:

2.3.4.pages用于定义每个页面入口组件的路由信息
➢ 每个页面由页面路径和页面名组成,页面的文件名就是页面名。
➢ pages列表中第一个页面为应用的首页入口。
➢ 页面文件名不能使用组件名称,比如:
Text.ets、Button.ets等。
➢ 每个页面文件中必须包含页面入口组件
(@Entry装饰)。


在config中pages里面的ets文件,谁在第一个,则先启动谁。
可以在index.ets文件中,创建点击事件,通过点击事件打开demopage.ets文件
index.ets
import router from '@ohos.router';
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(e=>{
router.pushUrl(//页面跳转到demopage'
{
url:'pages/demopage',
params:{//传递的参数值 name:'张飞', address:'北京' }
}
)
})
}
.width('100%');
Column() {
Text("我的FA项目")
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.margin(40)
.height('100%')
}
}
|
demopage.ets
import router from '@ohos.router';
@Entry
@Component
struct Demopage {
@State message: string = 'DemoPage'
//获取index.ets传递的参数值
@State sname: string = router.getParams()['name'] @State address: string = router.getParams()['address']
build() {
Column() {
Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) } .width('100%');
Column() { Text("姓名"+this.sname+",地址:"+this.address) .fontSize(50) .fontWeight(FontWeight.Bold) } .width('100%');
Column() { Text("返回首页") .fontSize(50) .fontWeight(FontWeight.Bold) .onClick(e=>{ router.pushUrl({ url:'pages/index'//指定跳转的路径
}) }) } .width('100%')
}
.height('100%')
}
}
|
运行结果:


-
- 资源管理及访问
资源定义:应用资源由开发者在工程的resources目录中定义,resources目录按照两级目录的形式来组织:
◼ 一级目录为base目录、限定词目录以及rawfile目录
➢ base目录是默认存在的目录,当应用的resources资源目录中没有与设备状态匹配的限定词目录时,会自动引用该目录中的资 源文件。
➢ 限定词目录需要开发者自行创建,其可以由一个或多个表征应用场景或设备特征的限定词组合而成。
➢ 在引用rawfile中的资源时,不会根据系统的状态去匹配,rawfile目录中可以直接存放资源文件。
◼ 二级目录为资源目录
➢ 用于存放字符串、颜色、浮点数等基础元素,以及媒体等资源文件。

-
-
- 资源的引用方式
1.在工程中,通过“$r('app.type.name')”的形式引用应用资源
◼ app代表是应用内resources目录中定义的资源。
◼ type代表资源类型(或资源的存放位置),可以取“color”、“float”、“string”、“plural”、“media”。
◼ name代表资源命名,由开发者定义资源时确定。
◼ 引用rawfile下资源时使用“$rawfile('filename')”的形式
◼ 当前$rawfile仅支持Image控件
引用图片资源。
◼ filename需要表示为rawfile目录 下的文件相对路径,文件名需要 包含后缀,路径开头不可以以“/”开头。
示例如下:
wangzhepage.ets
import media from '@ohos.multimedia.media'
import App from '@system.app'
@Entry
@Component
struct Wangzhepage {
@State message: string = 'Hello World'
build() {
Column() {
Column() {
Image($r("app.media.lb"))//加载media目录下的lb.png文件 .objectFit(ImageFit.Contain) .height(483) .width(563) } .width('100%');
Column() {
Text("这是刘邦的皮肤")
.fontSize(40)
.fontWeight(FontWeight.Bold)
.height(200)
.width(300)
}
.width('100%');
}
.height('100%')
}
}
|

运行效果:

课堂练习
- 完成两个页面之间的交互
- 引用图片,完成点击小图看大图的效果。(小图界面和大图界面是两个界面,通过传递参数确定图片的名称)
2.引用rawfile下资源时使用“$rawfile('filename')”的形式
◼ 当前$rawfile仅支持Image控件
引用图片资源。
◼ filename需要表示为rawfile目录 下的文件相对路径,文件名需要包含后缀,路径开头不可以以“/”开头。
示例:
import media from '@ohos.multimedia.media'
import App from '@system.app'
@Entry
@Component
struct Wangzhepage {
@State message: string = 'Hello World'
build() {
Column() {
Column() {
Image($r("app.media.lb"))//加载media目录下的lb.png文件
.objectFit(ImageFit.Contain)
.height(283)
.width(263)
}
.width('100%');
Column() {
Text("这是刘邦的皮肤")
.fontSize(40)
.fontWeight(FontWeight.Bold)
.height(200)
.width(300)
}
.width('100%');
//引用rawfile资源下的文件 Column() { Image($rawfile("dc.png"))//加载rawfile目录下的lb.png文件 .objectFit(ImageFit.Contain) .height(283) .width(263) } .width('100%');
}
.height('100%')
}
}
|


3.媒体资源格式说明:

- 像素单位及类型定义
像素单位:为开发者提供4种像素单位,框架采用vp为基准数据单位



示例如下:
@Entry
@Component
struct Chelizipage {
@State message: string = 'Hello World'
build() {
Flex({
direction:FlexDirection.Column,//指定弹性布局的方向为(Colum)垂直方向
alignItems:ItemAlign.Center,//选项居中对象
justifyContent:FlexAlign.Center//内容居中对齐
}){
//=======放置图片的区域===============
Image($r("app.media.chelizi"))
.objectFit(ImageFit.Fill)
.width(300)
.height("300vp")
.backgroundColor("#fff50965")//设置背景颜色
.rotate({x:0, y:0, z:1, centerX:'50%', centerY:'50%', angle:'45dep'})
.borderRadius(100);
//====================================
//=========放置文本的区域============
Text("车厘子")
.width("200VP")
.height("100vp")
.align(Alignment.Center)
.margin({left:110})
.fontSize("36fp")
.fontColor(Color.Red)
//==================================
}
.width("100%")
.height("100%")
}
}
|

三.声明式语法
3.1.通用UI描述基本概念
1.布局方式(Colum(垂直布局)或者Row(水平布局))
2.组件(Text文本组件、Button按钮组件等等)
3.事件(onClick点击事件)
示例:
@Entry
@Component
struct Demopage {
@State message: string = '你好世界'
build() {
Column() {
//文本=======================
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%');
//============================
Divider().width('100%').color(Color.Red).margin({top:20});//分隔符
//============================
Row(){
//=======放置按钮的位置=========
Button("点我1")
.width(110)
.height(50)
.fontSize("30fp")
.margin({top:20,left:50})
.onClick(e=>{//事件方法
this.message="你点击按钮1"
});
//============================
//=======放置按钮的位置=========
Button("点我2")
.width(110)
.height(50)
.fontSize("30fp")
.margin({top:20,left:20})
.onClick(e=>{//事件方法
this.message="你点击按钮2"
});
//============================
}
.width("100%")
.height("10%");
}
.height('100%')
.width("100%")
.margin({top:50})
}
}
|


示例2:按钮换图

@Entry
@Component
struct Wzimgpage {
@State message: string = 'Hello World'
@State images:Array<string>=['/pages/images/dc.png','/pages/images/dw.png']
@State pic:string=this.images[0]
build() {
Column() {
//=====放置图片的位置=========
Column() {
Image(this.pic)
.objectFit(ImageFit.Fill)
.width("100%")
.height("50%")
}
.width("100%")
//==========================
//======放置两个按钮的位置=======
//水平放置两个按钮====
Row(){
Button("貂蝉")
.width("110")
.height("50")
.margin({top:30})
.onClick(e=>{
this.pic=this.images[0]
})
;
Button("典韦")
.width("110")
.height("50")
.margin({top:30,left:10})
.onClick(e=>{
this.pic=this.images[1];
})
}
//=============================
}
.height('100%')
}
}
|


-
-
- 通用UI描述基本概念
基于TS扩展的声明式开发范式提供了一系列基础组件,这些组件以声明方式进行组合和扩展来描述应用程序的UI界 面,并且还提供了基本的数据绑定和事件处理机制,帮助开发者实现应用交互逻辑。
◼ 基本概念描述:
➢ 装饰器:方舟开发框架定义了一些具有特殊含义的装饰器,用于装饰类、结构、方法和变量。例如前面示例程
序中的@Entry、@Component和@State等。
➢ 自定义组件:可重用的UI单元,可以与其他组件组合。如@Component装饰的struct Hello。
➢ UI描述:声明性描述UI结构,例如build()方法中的代码块。
➢ 内置组件:框架中默认内置的基本组件和布局组件,开发者可以直接调用,如Column、 Text、Divider、
Button等。
➢ 属性方法:用于配置组件属性,如fontSize()、width()、height()、color()等。
➢ 事件方法:在事件方法的回调中添加组件响应逻辑。例如,为Button组件添加onClick方法,在onClick方法的 回调中添加点击响应逻辑。
在index.ets中添加按钮导航,导航到不同的ets路径
import router from '@ohos.router';
@Entry
@Component
struct Index {
@State message: string = '主页'
build() {
Column() {
//=================================
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.margin({top:10})
}.width('100%');
//=================================
Divider().width("100%").margin({top:10}).color(Color.Red);
//==============放置按钮导航=========
Button("车厘子").margin({top:20})
.onClick(e=>{
router.pushUrl({
url:'pages/chelizipage'
});
});
Button("按钮事件交互").margin({top:20})
.onClick(e=>{
router.pushUrl({
url:'pages/demopage'
});
});
Button("王者头像").margin({top:20})
.onClick(e=>{
router.pushUrl({
url:'pages/wzimgpage'
});
});
//=================================
}
.height('100%')
}
}
|
项目结构:





课堂练习
完成课堂案例,自己定义一些图片进行交换,并能够导航到其他页面
3.1.2.声明式UI描述规范
无参数构造配置 ➢ 组件的接口定义不包含必选构造参数,组件后面的“()”中不需要配置任何内容,例如:Divider()。Text()
必选参数构造配置 ➢ 如果组件的接口定义中包含必选构造参数,则在组件后面的“()”中必须配置参数,例如:Image组件的必选参数src,Text组件的必选参数content。
属性配置
➢ 使用属性方法配置组件的属性,属性方法紧随组件,并用“.”运算符连接。
➢ 使用“.”操作进行可以链式调用同时配置组件的多个属性。
➢ 除了直接传递常量参数外,还可以传递变量或表达式。
➢ 对于内置组件,框架还为其属性预定义了一些枚举类型,供开发人员调用,枚举值可以作为参数传递。
示例如下:
@Entry
@Component
struct Index {
build() {
Column(){
//==文本==========
Text("我的鸿蒙世界")
.fontColor(Color.Red)
.fontSize(36);
//===================
//===分隔符===========
Divider().width("100%").margin({top:20}).color(Color.Blue);//分隔符
//===================
//====设置网络图片=====
Image("http://www.softuc.com/images/bar-ad-001.png")
.objectFit(ImageFit.Fill)
.height(400)
.margin({top:50})
//===================
//===分隔符===========
Divider().width("100%").margin({top:50}).color(Color.Blue);//分隔符
//===================
//=====加入文本=======
Text("copyright 山东外国语职业技术大学")
.fontSize(16)
.margin({top:20})
//==================
}
.width("100%")
.height("100%")
.margin({top:40})
}
}
|

模拟器运行效果

3.1.3.事件配置
➢ 通过事件方法可以配置组件支持的事件。
◼ 实现方法
◼ 使用lambda表达式配置组件的事件方法。
◼ 使用匿名函数表达式配置组件的事件方法,要求使用bind,以确保函数体中的this引用包含的组件。
◼ 使用组件的成员函数配置组件的事件方法。
示例
给图片添加点击事件
@Entry
@Component
struct Index {
build() {
Column(){
//==文本==========
Text("我的鸿蒙世界")
.fontColor(Color.Red)
.fontSize(36);
//===================
//===分隔符===========
Divider().width("100%").margin({top:20}).color(Color.Blue);//分隔符
//===================
//====设置网络图片=====
Image("http://www.softuc.com/images/bar-ad-001.png")
.objectFit(ImageFit.Fill)
.height(400)
.margin({top:50})
.onClick(e=>{//匿名事件 AlertDialog.show({message:"无奋斗,不青春!"}) })
//===================
//===分隔符===========
Divider().width("100%").margin({top:50}).color(Color.Blue);//分隔符
//===================
//=====加入文本=======
Text("copyright 山东外国语职业技术大学")
.fontSize(16)
.margin({top:20})
//==================
}
.width("100%")
.height("100%")
.margin({top:40})
}
}
|

-
- 我的图册示例
文件结构:

示例如下:
mainpage.ets
import router from '@ohos.router'
@Entry
@Component
struct Mainpage {
@State message: string = 'Hello World'
//声明数组是json数组类型
photos =[
{'image':'/pages/images/a0.jpg','title':'并蒂荷花'},
{'image':'/pages/images/a1.jpg','title':'大漠黄沙'},
{'image':'/pages/images/a2.jpg','title':'静静地村庄'},
{'image':'/pages/images/a3.jpg','title':'小溪流水'},
{'image':'/pages/images/a4.jpg','title':'雪山丽景'},
{'image':'/pages/images/chelizi.jpg','title':'车厘子'},
{'image':'/pages/images/langua.jpg','title':'圣诞兰瓜'},
{'image':'/pages/images/pic1.jpg','title':'黄昏的芦苇'},
{'image':'/pages/images/pic2.jpg','title':'路灯女孩'},
{'image':'/pages/images/pic3.jpg','title':'东方之珠'},
{'image':'/pages/images/pic4.jpg','title':'银河璀璨'}
]
build() {
Column(){//定义垂直方向布局
Scroll(){//滚动面板
List(){
ForEach(this.photos,pt=>{//对photos数组进行循环
ListItem(){//设置list选项组件
//====行布局,一行两列=======
Row(){
//====图片====
Image(pt.image)
.objectFit(ImageFit.Fill)
.height(120);
//===图片结束===
Column(){
//===文本标签=====
Text(pt.title)
.fontSize(24)
//==文本标签结束====
//放置按钮=========
Button("显示详细")
.margin({top:20})
.onClick(e=>{
router.pushUrl({
url:'pages/photopage',
params:{
title:pt.title,
image:pt.image
}
})
});
//================
}.margin({left:20})
}
.margin(10)
//=====行布局结束============
}
})
}
}
}.width("100%")
.height("100%")
}
}
|
点击按钮后,能观察到的详细界面photopage.ets
import router from '@ohos.router';
@Entry
@Component
struct Photopage {
@State message: string = 'Hello World'
//接收参数的值
@State title:string=router.getParams()['title']
@State image:string =router.getParams()['image']
build() {
//console.log(this.title);
Column(){
//==文本==========
Text(this.title)
.fontColor(Color.Red)
.fontSize(36);
//===================
//===分隔符===========
Divider().width("100%").margin({top:20}).color(Color.Blue);//分隔符
//===================
//====设置网络图片=====
Image(this.image)
.objectFit(ImageFit.Fill)
.height(400)
.margin({top:50})
.onClick(e=>{//匿名事件
AlertDialog.show({message:"无奋斗,不青春!"})
})
//===================
//===分隔符===========
Divider().width("100%").margin({top:50}).color(Color.Blue);//分隔符
//===================
//=====加入文本=======
Text("copyright 山东外国语职业技术大学")
.fontSize(16)
.margin({top:20})
//==================
}
.width("100%")
.height("100%")
.margin({top:40})
}
}
|
效果预视


项目结构:

课堂练习
仿照课堂案例,实现图片列表和详细信息的展示
可以试着实现音乐歌曲列表或者电影解说列表和详细展示
3.3.组件化
3.3.1.@Component--组件
◼ @Component装饰的struct表示该结构体具有组件化能力,能够成为一个独立的组件,这种类型的组件也称为自定义组件,在build方法里描述UI结构。
◼ 自定义组件具有以下特点:
➢ 可组合:允许开发人员组合使用内置组件、其他组件、公共属性和方法;
➢ 可重用:自定义组件可以被其他组件重用,并作为不同的实例在不同的父组件或容器中使用;
➢ 生命周期:生命周期的回调方法可以在组件中配置,用于业务逻辑处理;
➢ 数据驱动更新:由状态变量的数据驱动,实现UI自动更新。
◼ 使用限制:
➢ 自定义组件必须定义build方法。
➢ 自定义组件禁止自定义构造函数
组件化示例:
import router from '@ohos.router'
import "common/commonbottom"
@Entry
@Component
struct Mainpage {
@State message: string = 'Hello World'
//声明数组是json数组类型
photos =[
{'image':'/pages/images/a0.jpg','title':'并蒂荷花'},
{'image':'/pages/images/a1.jpg','title':'大漠黄沙'},
{'image':'/pages/images/a2.jpg','title':'静静地村庄'},
{'image':'/pages/images/a3.jpg','title':'小溪流水'},
{'image':'/pages/images/a4.jpg','title':'雪山丽景'},
{'image':'/pages/images/chelizi.jpg','title':'车厘子'},
{'image':'/pages/images/langua.jpg','title':'圣诞兰瓜'},
{'image':'/pages/images/pic1.jpg','title':'黄昏的芦苇'},
{'image':'/pages/images/pic2.jpg','title':'路灯女孩'},
{'image':'/pages/images/pic3.jpg','title':'东方之珠'},
{'image':'/pages/images/pic4.jpg','title':'银河璀璨'}
]
build() {
Column(){//定义垂直方向布局
Scroll(){//滚动面板
List(){//列表组件
ForEach(this.photos,pt=>{//对photos数组进行循环
ListItem(){//设置list选项组件
//====行布局,一行两列=======
Row(){
//====图片====
Image(pt.image)
.objectFit(ImageFit.Fill)
.width(180)
.height(120);
//===图片结束===
Column(){
//===文本标签=====
Text(pt.title)
.fontSize(24)
//==文本标签结束====
//放置按钮=========
Button("显示详细")
.margin({top:20})
.onClick(e=>{
router.pushUrl({
url:'pages/photopage',
params:{
title:pt.title,
image:pt.image
}
})
})
.backgroundColor(Color.Orange);
//================
}.margin({left:20})
}
.margin(10)
//=====行布局结束============
}
})
}
}
MyButtomBar()
}.width("100%")
.height("90%");
}
}
//=============================================== //自定义组件 @Component struct MyButtomBar{ build(){ Row(){ Text("首页") .fontSize(25) .width("25%") .backgroundColor(Color.Yellow) .textAlign(TextAlign.Center); Text("收藏") .fontSize(25) .width("25%") .backgroundColor(Color.Yellow) .textAlign(TextAlign.Center) .margin({left:5}); Text("关注") .fontSize(25) .width("25%").backgroundColor(Color.Yellow) .textAlign(TextAlign.Center).margin({left:5}); Text("关于") .fontSize(25) .width("25%") .backgroundColor(Color.Yellow) .textAlign(TextAlign.Center) .margin({left:5}) }.width("100%") .height("10%") .backgroundColor(Color.Orange) .align(Alignment.Center) } }
|

3.3.2.@Entry--页面渲染的入口组件
◼ @Entry装饰的自定义组件用作页面的默认入口组件,加载页面时,将首先创建并呈现@Entry装饰的自定义组件。
◼ 使用限制:
➢ 在单个源文件中,最多可以使用@Entry装饰一个自定义组件。

3.3.3.@Builder --函数的修饰描述注解
◼ @Builder装饰的方法用于定义组件的声明式UI描述,在 一个自定义组件内快速生成多个布局内容。
◼ @Builder装饰方法的功能和语法规范与build函数相同。
3.3.4.外部组件的定义方式(自定义组件可以导出到其他页面使用)示例:
在MainAbility创建common文件夹,定义commonbottom.ets自定义组件
//自定义组件
import router from '@ohos.router';
@Component export struct MyButtomBar{
build(){
Row(){
this.writeText("首页");
this.writeText("收藏");
this.writeText("关注");
this.writeText("帮助");
}.width("100%")
.height("10%")
.backgroundColor(Color.Orange)
.align(Alignment.Center)
}
//定义函数,写出文本的信息并装饰 @Builder writeText(txt:string){ Text(txt) .fontSize(25) .width("25%") .backgroundColor(Color.Yellow) .textAlign(TextAlign.Center) .margin({left:5}) .onClick(e=>{ AlertDialog.show({ message:'进入'+txt }) if(txt=='首页'){ router.pushUrl({ url:'pages/mainpage' }) } }) }
//=======================================
}
|
在MainAbility创建common文件夹,定义commonhead.ets自定义组件
为头部组件

@Component
export struct MyHead{
build(){
Column(){
Image('/common/image/banner.jpg')
.objectFit(ImageFit.Fill)
.width('100%')
Row(){
//导航条====================================
this.writeCatalog("水果")
this.writeCatalog("蔬菜")
this.writeCatalog("干果")
this.writeCatalog("零食")
this.writeCatalog("粮油")
this.writeCatalog("肉食")
///========================================
}.width('100%')
}.width("100%")
.height("15%")
}
@Builder writeCatalog(ca : string){
Text(ca)
.width('20%')
.fontSize(24)
.textAlign(TextAlign.Center)
.backgroundColor(Color.Yellow)
.margin({left:5})
}
}
|

在pages目录下的mainpage.ets下引入自定义的头部和底部组件
import router from '@ohos.router' import { MyButtomBar } from '../common/commonbottom' import { MyHead } from '../common/commonhead'
@Entry
@Component
struct Mainpage {
@State message: string = 'Hello World'
//声明数组是json数组类型
photos =[
{'image':'/pages/images/a0.jpg','title':'并蒂荷花'},
{'image':'/pages/images/a1.jpg','title':'大漠黄沙'},
{'image':'/pages/images/a2.jpg','title':'静静地村庄'},
{'image':'/pages/images/a3.jpg','title':'小溪流水'},
{'image':'/pages/images/a4.jpg','title':'雪山丽景'},
{'image':'/pages/images/chelizi.jpg','title':'车厘子'},
{'image':'/pages/images/langua.jpg','title':'圣诞兰瓜'},
{'image':'/pages/images/pic1.jpg','title':'黄昏的芦苇'},
{'image':'/pages/images/pic2.jpg','title':'路灯女孩'},
{'image':'/pages/images/pic3.jpg','title':'东方之珠'},
{'image':'/pages/images/pic4.jpg','title':'银河璀璨'}
]
build() {
Column(){//定义垂直方向布局
MyHead()//调用头部组件
Scroll(){//滚动面板
List(){//列表组件
ForEach(this.photos,pt=>{//对photos数组进行循环
ListItem(){//设置list选项组件
//====行布局,一行两列=======
Row(){
//====图片====
Image(pt.image)
.objectFit(ImageFit.Fill)
.width(180)
.height(120);
//===图片结束===
Column(){
//===文本标签=====
Text(pt.title)
.fontSize(24)
//==文本标签结束====
//放置按钮=========
Button("显示详细")
.margin({top:20})
.onClick(e=>{
router.pushUrl({
url:'pages/photopage',
params:{
title:pt.title,
image:pt.image
}
})
})
.backgroundColor(Color.Orange);
//================
}.margin({left:20})
}
.margin(10)
//=====行布局结束============
}
})
}
}.margin({top:40})
MyButtomBar().margin({bottom:0})//调用底部组件
}.width("100%")
.height("80%");
}
}
|


课堂练习
仿照课堂示例,实现自己作品的列表和内容展示,以及导航等界面效果
3.5.UI组件状态管理
◼ 在声明式UI编程范式中,UI是应用程序状态的函数,开发人员通过修改当前应用程序状态来更新相应的UI界面。
◼ @State状态变量装饰器:组件拥有的状态属性,当@State装饰的变量更改时,组件会重新渲染更新UI。
◼ @State装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的build方法进行UI刷新。
◼ @State状态数据具有以下特征:
➢ 支持多种类型:允许class、number、boolean、string强类型的按值和按引用类型。允许这些强类型构成的数组,即Array<class>、Array<string>、Array<boolean>、Array<number>。不允许object和any。
➢ 支持多实例:组件不同实例的内部状态数据独立。
➢ 内部私有:标记为@State的属性是私有变量,只能在组件内访问。
➢ 需要本地初始化:必须为所有@State变量分配初始值,将变量保持未初始化可能导致框架行为未定义。
➢ 创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定@State状态
属性的初始值
示例:
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State count :number=0;
@State sdate:string="2024-11-27 14:22:12"
build() {
Column(){
//放置文本标签
Text("点击次数:"+this.count) .width("100%") .fontSize(24) .fontWeight(FontWeight.Bold) .margin({left:220,top:200})
//=============
//放置按钮
Button("点击计数") .fontSize(20) .width(120) .margin({top:20,left:-10}) .onClick(e=>{ this.count++ });
Text(this.sdate)
.width("100%")
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({left:220,top:200})
.onClick(e=>{
this.sdate="2024-11-12"
})
};
}
}
|
点击计数器,count值会不断累加

3.6.渲染控制语法
3.6.1.使用if...else控制界面元素的变化
@Entry @Component struct Photopage {
@State message: string = 'Hello World'
@State gender:string="boy"
build() {
Column() {
Column() {
if (this.gender=='boy'){
Image("/pages/image/man.jpg")
.objectFit(ImageFit.Fill)
.width("100%")
.width("100%")
}else{
Image("/pages/image/girl.jpg")
.objectFit(ImageFit.Fill)
.width("100%")
.width("100%")
}
Button("女")
.width(200)
.margin({top:20})
.onClick(e=>{
this.gender='girl';
})
Button("男")
.width(200)
.margin({top:20})
.onClick(e=>{
this.gender='boy';
})
}
.height('100%')
}
} }
|


3.6.2.使用forEach进行循序渲染
循环渲染:
◼ 开发框架提供循环渲染(ForEach组件)来迭代数组,并为每个数组项创建相应的组件。
◼ ForEach(arr: any[],itemGenerator: (item: any, index?: number) => void, keyGenerator?: (item: any, index?: number) =>
string):void

示例如下:
@Entry
@Component
struct Arrayforpage {
@State message: string = 'Hello World'
@State citys:Array<string>=['北京','上海','深圳','大连','西安','重庆','成都','香港']
build() {
Flex({
direction:FlexDirection.Column,
alignItems:ItemAlign.Center,
justifyContent:FlexAlign.Center
}){
ForEach(this.citys,item=>{
Divider().margin({top:20})
Text(item)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({top:20,left:100})
})
}
}
}
|

带有List组件的for循环
@Entry
@Component
struct Arrayforpage {
@State message: string = 'Hello World'
@State citys:Array<string>=['北京','上海','深圳','大连','西安','重庆',
'成都','香港','澳门','长沙','郑州','开封','济南','长安']
build() {
Flex({
direction:FlexDirection.Column,
alignItems:ItemAlign.Center,
justifyContent:FlexAlign.Center
}){
List(){
ForEach(this.citys,item=>{
ListItem(){
Column(){
Divider().margin({top:20})
Text(item)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.margin({left:100,top:20})
}
}
})
}
}
}
}
|
List组件里面只能有一个ListItem组件,ListItem里面只能有一个UI组件,例如COLUNM
3.6.3.使用List组件和Video组件构建视频播放示例
1.构建视频类型文件video.ets(commons目录)
export interface VideoType{
videoimg:string;//视频的图片
videosource:Resource;//视频mp4的资源
title:string;//标题
note:string;//内容简介
}
|
2.构建主界面,用于要播放的视频列表
index.ets
import router from '@ohos.router';
import { VideoType } from "../commons/video" //引用类型
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State videoarray:Array<VideoType>=[
{'videoimg':'/pages/image/m1.jpg','videosource':$rawfile("m1.mp4"),'title':'羊羊月,你是不是疯了','note':'大学生就业的困惑问题涉及多个方面,需要政府、高校、用人单位以及毕业生本人共同努力来解决。政府应加大对就业市场的监管和调控力度,提供更多的就业机会和培训资源;高校应加强对学生的职业规划和就业指导服务,提高学生的实践能力和综合素质;用人单位应摒弃不合理的歧视现象,为毕业生提供更多的发展机会和平台;毕业生本人则应积极调整心态,提高自身的竞争力,同时也要有现实的认识,适应市场的需求。'},
{'videoimg':'/pages/image/m2.jpg','videosource':$rawfile("m2.mp4"),'title':'英国博主:中国将欧美科幻电影变成了现实','note':'从科技发展的角度来看,中国的科技水平在近年来取得了显著进步。在许多领域,如人工智能、无人机技术、高速铁路等,中国都取得了令人瞩目的成就。这些技术的发展不仅推动了经济的增长,也改善了人们的生活质量。因此,当英国博主看到中国在这些领域的进步时,他可能会认为中国已经将欧美科幻电影中的一些场景变成了现实。'},
{'videoimg':'/pages/image/m3.jpg','videosource':$rawfile("m3.mp4"),'title':'这个广告真的惊艳我好多年,小时候在电视上看到也不会换台跳过','note':'一个能够让人惊艳多年的广告,通常具备独特的创意、精良的制作、情感共鸣以及深刻的童年记忆等特点。这些特点共同构成了广告的魅力,让观众在观看的过程中产生强烈的共鸣和记忆。'},
{'videoimg':'/pages/image/m4.jpg','videosource':$rawfile("m4.mp4"),'title':'端庄华贵,这就是长公主的模样了吧','note':'在宫廷剧或者古装剧中,这样的赞美可能更加贴切和符合剧情需要;而在现实生活中,这样的赞美则可能更多地是一种对女性气质和修养的赞美。'},
{'videoimg':'/pages/image/m5.jpg','videosource':$rawfile("m5.mp4"),'title':'男人的眼泪,女人的兴奋剂','note':'男性流泪通常被视为一种情感的真实流露,可能代表着他们内心的脆弱、悲伤或痛苦。对于某些女性来说,看到男性流泪可能会引发她们的同情、关心和爱护之心,从而产生一种想要支持和帮助对方的冲动。这种情况下,男性的眼泪确实可能像一种“兴奋剂”,激发女性内心的柔情和力量。'},
{'videoimg':'/pages/image/m6.jpg','videosource':$rawfile("m6.mp4"),'title':'原始人第一次吃火锅','note':'原始人因为火锅的美味而场面失控,直接上手抢食。这反映了人类在面对新鲜事物和美味诱惑时的本能反应,即想要尽快获取并享受这种美味。这种反应在原始社会中尤为常见,因为食物资源的稀缺性使得人们更加珍惜和渴望每一份食物。'},
];
build() {
Column(){
Column(){
Scroll(){
List(){//列表组件
ForEach(this.videoarray,(videitem:VideoType)=>{
ListItem(){
Column(){
Divider().margin({top:10})
Row(){
//======设置图片==================
Image(videitem.videoimg)
.objectFit(ImageFit.Fill)
.width("40%")
.height(100)
//==============================
//========放置标题和按钮==========
Column(){
//放置文本===========
Text(videitem.title)
.width("40%")
.fontSize(10)
.fontWeight(FontWeight.Bold)
Button("点击观看")
.fontSize(10)
.width(80)
.margin({top:20})
//===================
}.margin({left:10})
.onClick(e=>{
router.pushUrl({
url:'pages/videoplaypage',
params:{
'item':videitem
}
})
})
//==============================
}.margin({top:20,left:0})
}
}
})
}
}
}
}.width("100%")
.height("100%")
}
}
|

3.构建视频播放页面videoplaypage.ets
import router from '@ohos.router'
import { VideoType } from '../commons/video'
@Entry
@Component
struct Videoplaypage {
@State message: string = 'Hello World'
@State videitem:VideoType=router.getParams()['item']
build() {
Column(){
Column(){
//放置标题======================
Text(this.videitem.title)
.fontSize(12)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
}.width("100%")
.margin({top:20})
//==============================
Divider().margin({top:20})//分割线
//=====放置视频组件===============
Video({
src:this.videitem.videosource
})
.autoPlay(true)//自动播放
.aspectRatio(16/9)//设置长宽比
.margin({top:20})
//==============================
Divider().margin({top:20})//分割线
Column(){
Text("内容简介")
.fontSize(16)
.fontWeight(FontWeight.Bold)
}.margin({top:20})
//==============================
Divider().margin({top:20})//分割线
//=====放置简洁的内容===========
Scroll(){
Column(){
Text(this.videitem.note)
.fontSize(10)
.fontWeight(FontWeight.Bold)
.lineHeight(20)
}
}
//===========================
}
}
}
|

- 编辑视频播放器的图标
修改config.json文件
"abilities": [
{
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"action.system.home"
]
}
],
"orientation": "unspecified",
"visible": true,
"srcPath": "MainAbility",
"name": ".MainAbility",
"srcLanguage": "ets",
"icon": "$media:videmoicon",
"description": "$string:MainAbility_desc",
"formsEnabled": false,
"label": "$string:MainAbility_label",
"type": "page",
"launchType": "standard"
}
],
|

项目目录结构:

启动模拟器部署项目,运行效果:



四.鸿蒙开发的常用组件
4.1.空白填充组件Blank
◼ 空白填充组件,在容器主轴方向上,空白填充组件具有自动填充容器空余部分的能力。
◼ 接口 :Blank(min?: Length)


示例如下:
Index.ets
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column(){
Row(){
Text("美颜增效")
.fontSize(30)
.fontWeight(FontWeight.Bold)
Blank();
Text("开/关")
.fontSize(30)
.fontWeight(FontWeight.Bold)
}.padding(12)
.width("100%")
.backgroundColor(Color.White)
.borderRadius(20)
}.backgroundColor("#CCCCCC")
.padding(20)
}
}
|

4.2.按钮组件Button


@Entry
@Component
struct ButtonExample {
build() {
Column() {
Button('按钮1')
Button('按钮2',{type:ButtonType.Normal}).margin({top:10})
Button('按钮3',{type:ButtonType.Normal,stateEffect:false}).margin({top:10})
Button({type:ButtonType.Circle}) {
Image($r("app.media.icon")).width(30).height(30)
}.width(60).height(60).backgroundColor(0x317aff).margin({top:10})
Button() {
Row(){
Image($r("app.media.ic_loading")).width(20).height(20)
Text('loading').fontSize(16).fontColor(Color.White)
}
}.width(100).backgroundColor(Color.Orange).margin({top:10})
}
.width('100%').height('100%').padding(20)
}
}
|
给按钮添加图标示例:
import media from '@ohos.multimedia.media'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column(){
Row(){
Text("美颜增效")
.fontSize(30)
.fontWeight(FontWeight.Bold)
Blank();
Text("开/关")
.fontSize(30)
.fontWeight(FontWeight.Bold)
}.padding(12)
.width("100%")
.backgroundColor(Color.White)
.borderRadius(20)
Column(){
Button(){
Row(){
Image($r("app.media.power"))
.objectFit(ImageFit.Fill)
.width(50)
.height(50)
Text("停止")
.margin({left:30})
.fontSize(28)
}
}.width("80%")
.height("10%")
.margin({top:50})
.backgroundColor(Color.White)
}
}.backgroundColor("#CCCCCC")
.padding(20)
}
}
|

4.3.分隔符组件Divider

import media from '@ohos.multimedia.media'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column(){
Row(){
Text("美颜增效")
.fontSize(30)
.fontWeight(FontWeight.Bold)
Blank();
Text("开/关")
.fontSize(30)
.fontWeight(FontWeight.Bold)
}.padding(12)
.width("100%")
.backgroundColor(Color.White)
.borderRadius(20)
//分隔符 Divider().width("100%").color(Color.White).margin({top:20})
Column(){
Button(){
Row(){
Image($r("app.media.power"))
.objectFit(ImageFit.Fill)
.width(50)
.height(50)
Text("停止")
.margin({left:30})
.fontSize(28)
}
}.width("80%")
.height("10%")
.margin({top:50})
.backgroundColor(Color.White)
}
}.backgroundColor("#CCCCCC")
.padding(20)
}
}
|
Divder分隔符垂直放置
import media from '@ohos.multimedia.media'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column(){
Row(){
Text("美颜增效")
.fontSize(30)
.fontWeight(FontWeight.Bold)
Blank();
Text("开/关")
.fontSize(30)
.fontWeight(FontWeight.Bold)
}.padding(12)
.width("100%")
.backgroundColor(Color.White)
.borderRadius(20)
Column(){
//分隔符
Divider().width("100%").color(Color.White).margin({top:20})
Row(){
Text("新闻").fontSize(10).margin({left:40})
Divider().vertical(true).color(Color.Green) .width(10).height(25).margin({left:5})
Text("财经").fontSize(10).margin({left:10})
Divider().vertical(true).color(Color.Green) .width(10).height(25).margin({left:5})
Text("军事").fontSize(10).margin({left:10})
Divider().vertical(true).color(Color.Green) .width(10).height(25).margin({left:5})
Text("体育").fontSize(10).margin({left:10})
Divider().vertical(true).color(Color.Green) .width(10).height(25).margin({left:5})
Text("娱乐").fontSize(10).margin({left:10})
Divider().vertical(true).color(Color.Green) .width(10).height(25).margin({left:5})
Text("游戏").fontSize(10).margin({left:10})
}.width("100%")
.height("10%")
.backgroundColor(Color.Yellow).margin({top:20})
Divider().width("100%").color(Color.White).margin({top:20})
Button(){
Row(){
Image($r("app.media.power"))
.objectFit(ImageFit.Fill)
.width(50)
.height(50)
Text("停止")
.margin({left:30})
.fontSize(28)
}
}.width("80%")
.height("10%")
.margin({top:50})
.backgroundColor(Color.White)
}
}.backgroundColor("#CCCCCC")
.padding(20)
}
}
|

4.4.Image图片组件


4.5.常用容器组件
4.5.1.Flex
◼ 弹性布局组件。
◼ 接口:Flex(options?: { direction?: FlexDirection, wrap?: FlexWrap, justifyContent?: FlexAlign, alignItems?:
ItemAlign, alignContent?: FlexAlign })



示例如下:flexpage.ets
@Entry
@Component
struct Flexpage {
@State message: string = 'Hello World'
@State navtitle:Array<string> =['玫瑰茶','茉莉茶','橄榄茶','红月茶','桂圆茶','枸杞茶','红枣茶']
build() {
Flex({
direction:FlexDirection.Column,//垂直放置组件
alignItems:ItemAlign.Start,
justifyContent:FlexAlign.Start,
}){
//=====布局1
Flex({
direction:FlexDirection.Row,
justifyContent:FlexAlign.SpaceEvenly
}){
ForEach(this.navtitle,(item:string)=>{
this.setTitle(item)
})
}.backgroundColor(Color.Pink)
.width("100%")
.height("10%")
.padding(10)
//==布局2
Flex({
direction:FlexDirection.Column,
}){
Image("/pages/images/hy.png")
.objectFit(ImageFit.Contain)
}.width("100%")
.height("70%")
.backgroundColor("#ffccff")
}
.width("100%")
.height("100%")
}
@Builder setTitle(title:string){
Divider().vertical(true).width(5).color("#ffccff")
Text(title)
.width(150)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.backgroundColor("#D8D5F5E7")
.margin({top:20})
}
}
|

4.5.2.容器组件之Column列组件
在垂直方向放置组件,每个组件在容器中占用独立的一行。


4.5.3.容器组件Row行组件
在一行上放置多个组件。


4.6.输入组件
4.6.1.文本框组件TextInput
1.使用方式
TextInput(placeholder:’提示信息’).type(InputType.Normal)
2.获取文本框的值
使用onChange事件获取文本框的值。
示例:
使用文本框构建用户登录,在登陆成功的页面显示用户的账号和密码。
index.ets
import router from '@ohos.router'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string=''
@State passwd:string=''
build() {
Column({space:20}){
Column(){
Image($r("app.media.bg"))
.objectFit(ImageFit.Fill)
.width('100%')
.height("20%")
}
Text("用户注册")
.fontSize(36)
.fontWeight(FontWeight.Bold)
Divider().width("100%")
//=======账号的输入框========
Row({space:15}){
Text("账号:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.onChange(v=>{//用于获取文本框值
this.uname=v;
})
}.width("100%").padding(20)
//===========================
//=======密码的输入框========
Row({space:15}){
Text("密码:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.type(InputType.Password)
.onChange(v=>{
this.passwd=v;
})
}.width("100%").padding(20)
//===========================
Divider().width("100%")
//=======密码的输入框========
Row({space:15}){
Button("确定")
.onClick(e=>{
router.pushUrl({
url:'pages/resultpage',
params:{
'uname':this.uname,
'passwd':this.passwd
}
})
})
Button("重置").onClick(e=>{
})
}.padding(20)
//===========================
}.width("100%")
.height("100%")
}
}
|
resultpage.ets
import router from '@ohos.router'
@Entry
@Component
struct Resultpage {
@State message: string = 'Hello World'
//获取上个页面传第的账号和密码
@State uname:string=router.getParams()['uname']
@State passwd:string=router.getParams()['passwd']
build() {
Column({space:20}){
Row({space:40}){
Text("账号:")
Text(this.uname)
}
Row({space:40}){
Text("密码:")
Text(this.passwd)
}
}.margin({top:200})
}
}
|


4.6.2.单选按钮Radio
单选框,提供相应的用户交互选择项。
接口
Radio(options: {value: string, group: string})
示例如下:
import router from '@ohos.router'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string=''
@State passwd:string=''
@State gender:string='男'
build() {
Column({space:20}){
Column(){
Image($r("app.media.bg"))
.objectFit(ImageFit.Fill)
.width('100%')
.height("20%")
}
Text("用户注册")
.fontSize(36)
.fontWeight(FontWeight.Bold)
Divider().width("100%")
//=======账号的输入框========
Row({space:15}){
Text("账号:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.onChange(v=>{//用于获取文本框值
this.uname=v;
})
}.width("100%").padding(20)
//===========================
//=======密码的输入框========
Row({space:15}){
Text("密码:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.type(InputType.Password)
.onChange(v=>{
this.passwd=v;
})
}.width("100%").padding(20)
//===========================
//======单选按钮==============
Row({space:10}){ Text("性别:") .fontSize(16) .fontWeight(FontWeight.Bold)
Radio({ value:'男', group:'gendergroup' }).checked(true) .onChange(v=>{ this.gender="男"; }) Text("男")
Radio({ value:'女', group:'gendergroup' }).onChange(v=>{ this.gender="女"; }) Text("女") }.margin({left:-150})
//==========================
Divider().width("100%")
//=======密码的输入框========
Row({space:15}){
Button("确定")
.onClick(e=>{
router.pushUrl({
url:'pages/resultpage',
params:{
'uname':this.uname,
'passwd':this.passwd
}
})
})
Button("重置").onClick(e=>{
})
}.padding(20)
//===========================
}.width("100%")
.height("100%")
}
} |
resultpage.ets
import router from '@ohos.router'
@Entry
@Component
struct Resultpage {
@State message: string = 'Hello World'
//获取上个页面传第的账号和密码
@State uname:string=router.getParams()['uname']
@State passwd:string=router.getParams()['passwd']
@State gender:string=router.getParams()['gender']
build() {
Column({space:20}){
Row({space:40}){
Text("账号:")
Text(this.uname)
}
Row({space:40}){
Text("密码:")
Text(this.passwd)
}
Row({space:40}){
Text("性别:")
Text(this.gender)
}
}.margin({top:200})
}
}
|




4.6.3.下拉列表框Select
提供下拉选择菜单,可以让用户在多个选项之间选择。
Select(options: Array<SelectOption>)
SelectOption

示例:
import router from '@ohos.router'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string=''
@State passwd:string=''
@State gender:string='男'
//用于填充下拉列表框的数组 @State edus:Array<SelectOption>=[ {value:'高中'}, {value:'大学'}, {value:'研究生'}, {value:'博士'}, {value:'博士后'} ] //获取下拉列表框选中的值 @State eduvalue:string='高中'
build() {
Column({space:20}){
Column(){
Image($r("app.media.bg"))
.objectFit(ImageFit.Fill)
.width('100%')
.height("20%")
}
Text("用户注册")
.fontSize(36)
.fontWeight(FontWeight.Bold)
Divider().width("100%")
//=======账号的输入框========
Row({space:15}){
Text("账号:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.onChange(v=>{//用于获取文本框值
this.uname=v;
})
}.width("100%").padding(20)
//===========================
//=======密码的输入框========
Row({space:15}){
Text("密码:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.type(InputType.Password)
.onChange(v=>{
this.passwd=v;
})
}.width("100%").padding(20)
//===========================
//======单选按钮==============
Row({space:10}){
Text("性别:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
Radio({
value:'男',
group:'gendergroup'
}).checked(true)
.onChange(v=>{
this.gender="男";
})
Text("男")
Radio({
value:'女',
group:'gendergroup'
}).onChange(v=>{
this.gender="女";
})
Text("女")
}.margin({left:-150})
//==========================
//======下拉列表框======
Row({space:15}){ Text("学历:") .fontSize(16) .fontWeight(FontWeight.Bold) Select(this.edus).width(200) .value("高中") .onSelect((index,value)=>{ this.eduvalue=value; })
}.padding(20).margin({left:-70})
//====================
Divider().width("100%")
//=======密码的输入框========
Row({space:15}){
Button("确定")
.onClick(e=>{
router.pushUrl({
url:'pages/resultpage',
params:{
'uname':this.uname,
'passwd':this.passwd,
'gender':this.gender,
'edu':this.eduvalue
}
})
})
Button("重置").onClick(e=>{
})
}.padding(20)
//===========================
}.width("100%")
.height("100%")
}
}
|
resultpage.ets
import router from '@ohos.router'
@Entry
@Component
struct Resultpage {
@State message: string = 'Hello World'
//获取上个页面传第的账号和密码
@State uname:string=router.getParams()['uname']
@State passwd:string=router.getParams()['passwd']
@State gender:string=router.getParams()['gender']
@State edu:string=router.getParams()['edu']
build() {
Column({space:20}){
Row({space:40}){
Text("账号:")
Text(this.uname)
}
Row({space:40}){
Text("密码:")
Text(this.passwd)
}
Row({space:40}){
Text("性别:")
Text(this.gender)
}
Row({space:40}){
Text("学历:")
Text(this.edu)
}
}.margin({top:200})
}
}
|


4.6.4.复选框CheckBox
提供多选框组件,通常用于某选项的打开或关闭。
接口
Checkbox(options?: {name?: string, group?: string })


示例:
index.ets
import router from '@ohos.router'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string=''
@State passwd:string=''
@State gender:string='男'
//用于填充下拉列表框的数组
@State edus:Array<SelectOption>=[
{value:'高中'},
{value:'大学'},
{value:'研究生'},
{value:'博士'},
{value:'博士后'}
]
//获取下拉列表框选中的值
@State eduvalue:string='高中'
//用于渲染复选框的数组
@State hobys:Array<object>=[ {name:'足球',group:'hobygroup'}, {name:'篮球',group:'hobygroup'}, {name:'网球',group:'hobygroup'}, {name:'台球',group:'hobygroup'} ] //复选框选中的值的数组 @State hobyvalues:Array<string>=[]
build() {
Column({space:20}){
Column(){
Image($r("app.media.bg"))
.objectFit(ImageFit.Fill)
.width('100%')
.height("20%")
}
Text("用户注册")
.fontSize(36)
.fontWeight(FontWeight.Bold)
Divider().width("100%")
//=======账号的输入框========
Row({space:15}){
Text("账号:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.onChange(v=>{//用于获取文本框值
this.uname=v;
})
}.width("100%").padding(20)
//===========================
//=======密码的输入框========
Row({space:15}){
Text("密码:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.type(InputType.Password)
.onChange(v=>{
this.passwd=v;
})
}.width("100%").padding(20)
//===========================
//======单选按钮==============
Row({space:10}){
Text("性别:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
Radio({
value:'男',
group:'gendergroup'
}).checked(true)
.onChange(v=>{
this.gender="男";
})
Text("男")
Radio({
value:'女',
group:'gendergroup'
}).onChange(v=>{
this.gender="女";
})
Text("女")
}.margin({left:-150})
//==========================
//======下拉列表框======
Row({space:15}){
Text("学历:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
Select(this.edus).width(200)
.value("高中")
.onSelect((index,value)=>{
this.eduvalue=value;
})
}.padding(20).margin({left:-70})
//====================
//=====复选框=============
Row({space:5}){ Text("爱好:") .fontSize(16) .fontWeight(FontWeight.Bold)
ForEach(this.hobys,(item,index)=>{ Row(){ Checkbox(item.name) .onChange(v=>{ this.hobyvalues.push(item.name)//获取选中的复选框值 }) Text(item.name) }
})
}.padding(20)
//=======================
Divider().width("100%")
//=======密码的输入框========
Row({space:15}){
Button("确定")
.onClick(e=>{
router.pushUrl({
url:'pages/resultpage',
params:{
'uname':this.uname,
'passwd':this.passwd,
'gender':this.gender,
'edu':this.eduvalue,
'hobys':this.hobyvalues
}
})
})
Button("重置").onClick(e=>{
})
}.padding(20)
//===========================
}.width("100%")
.height("100%")
}
}
|
resultpage.ets
import router from '@ohos.router'
@Entry
@Component
struct Resultpage {
@State message: string = 'Hello World'
//获取上个页面传第的账号和密码
@State uname:string=router.getParams()['uname']
@State passwd:string=router.getParams()['passwd']
@State gender:string=router.getParams()['gender']
@State edu:string=router.getParams()['edu']
@State hobys:Array<string>=router.getParams()['hobys']
build() {
Column({space:20}){
Row({space:40}){
Text("账号:")
Text(this.uname)
}
Row({space:40}){
Text("密码:")
Text(this.passwd)
}
Row({space:40}){
Text("性别:")
Text(this.gender)
}
Row({space:40}){
Text("学历:")
Text(this.edu)
}
Row({space:40}){ Text("爱好:") Text(this.hobys.join(",")) }
}.margin({top:200})
}
}
|


4.6.5.TextArea文本域
多行文本输入框组件,当输入的文本内容超过组件宽度时会自动换行显示。
接口
TextArea(value?:{placeholder?: ResourceStr, text?: ResourceStr, controller?: TextAreaController})

示例
import router from '@ohos.router'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string=''
@State passwd:string=''
@State gender:string='男'
//用于填充下拉列表框的数组
@State edus:Array<SelectOption>=[
{value:'高中'},
{value:'大学'},
{value:'研究生'},
{value:'博士'},
{value:'博士后'}
]
//获取下拉列表框选中的值
@State eduvalue:string='高中'
//用于渲染复选框的数组
@State hobys:Array<object>=[
{name:'足球',group:'hobygroup'},
{name:'篮球',group:'hobygroup'},
{name:'网球',group:'hobygroup'},
{name:'台球',group:'hobygroup'}
]
//复选框选中的值的数组
@State hobyvalues:Array<string>=[]
//定义备注变量 @State note:string=''
build() {
Column({space:20}){
Column(){
Image($r("app.media.bg"))
.objectFit(ImageFit.Fill)
.width('100%')
.height("20%")
}
Text("用户注册")
.fontSize(36)
.fontWeight(FontWeight.Bold)
Divider().width("100%")
// Scroll(){
Column(){
//=======账号的输入框========
Row({space:15}){
Text("账号:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.onChange(v=>{//用于获取文本框值
this.uname=v;
})
}.width("100%").padding(20)
//===========================
//=======密码的输入框========
Row({space:15}){
Text("密码:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextInput({placeholder:'请输入账号'})
.width("70%")
.type(InputType.Password)
.onChange(v=>{
this.passwd=v;
})
}.width("100%").padding(20)
//===========================
//======单选按钮==============
Row({space:10}){
Text("性别:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
Radio({
value:'男',
group:'gendergroup'
}).checked(true)
.onChange(v=>{
this.gender="男";
})
Text("男")
Radio({
value:'女',
group:'gendergroup'
}).onChange(v=>{
this.gender="女";
})
Text("女")
}.margin({left:-150})
//==========================
//======下拉列表框======
Row({space:15}){
Text("学历:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
Select(this.edus).width(200)
.value("高中")
.onSelect((index,value)=>{
this.eduvalue=value;
})
}.padding(20).margin({left:-70})
//====================
//=====复选框=============
Row({space:5}){
Text("爱好:")
.fontSize(16)
.fontWeight(FontWeight.Bold)
ForEach(this.hobys,(item,index)=>{
Row(){
Checkbox(item.name)
.onChange(v=>{
this.hobyvalues.push(item.name)//获取选中的复选框值
})
Text(item.name)
}
})
}.padding(20)
Column({space:5}){
Text("备注")
.fontSize(16)
.fontWeight(FontWeight.Bold)
TextArea().width('100%') .height(120) .onChange(v=>{ this.note=v; })
}.padding(20)
//=======================
}.width('100%').height("50%")
// }.scrollable(ScrollDirection.Vertical)
// .scrollBar(BarState.Auto)
Divider().width("100%")
//=======按钮========
Row({space:15}){
Button("确定")
.onClick(e=>{
router.pushUrl({
url:'pages/resultpage',
params:{
'uname':this.uname,
'passwd':this.passwd,
'gender':this.gender,
'edu':this.eduvalue,
'hobys':this.hobyvalues,
'note':this.note
}
})
})
Button("重置").onClick(e=>{
})
}.padding(20)
//===========================
}.width("100%")
.height("100%")
}
}
|
resultpage.ets
import router from '@ohos.router'
@Entry
@Component
struct Resultpage {
@State message: string = 'Hello World'
//获取上个页面传第的账号和密码
@State uname:string=router.getParams()['uname']
@State passwd:string=router.getParams()['passwd']
@State gender:string=router.getParams()['gender']
@State edu:string=router.getParams()['edu']
@State hobys:Array<string>=router.getParams()['hobys']
@State note:string=router.getParams()['note']
build() {
Column({space:20}){
Row({space:40}){
Text("账号:")
Text(this.uname)
}
Row({space:40}){
Text("密码:")
Text(this.passwd)
}
Row({space:40}){
Text("性别:")
Text(this.gender)
}
Row({space:40}){
Text("学历:")
Text(this.edu)
}
Row({space:40}){
Text("爱好:")
Text(this.hobys.join(","))
}
Row({space:40}){
Text("备注:")
Text(this.note)
}
}.margin({top:200})
}
}
|


4.7.鸿蒙的全局UI
4.7.1.警告弹窗
◼ AlertDialog显示警告弹窗组件,可设置文本内容与响应回调。
◼ 方法属性

paramObject1参数:

paramObject2参数:

示例如下:
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string='';
@State passwd:string='';
build() {
Column(){
Column(){
Text("用户登录").margin({top:50})
TextInput({
placeholder:'请输入姓名:'
})
.width("80%")
.margin({top:50})
.onChange(value=>{
//获取文本框的值
this.uname=value;
})
TextInput({
placeholder:'请输入密码:'
}).type(InputType.Password)
.width("80%")
.margin({top:50})
.onChange(value=>{
//获取文本框的值
this.passwd=value;
})
Button("确定").width("50%").margin({top:50})
.onClick(e=>{
AlertDialog.show({ title:'接收的信息', message:"姓名:"+this.uname+"\n密码:"+this.passwd, confirm:{ value:'确定', action:()=>{ console.log("确定") } }, cancel:()=>{ console.log("取消") } });
})
}
}.width("100%")
.height("100%")
}
}
|

警告弹窗(两个按钮) 示例:
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string='';
@State passwd:string='';
build() {
Column(){
Column(){
Text("用户登录").margin({top:50})
TextInput({
placeholder:'请输入姓名:'
})
.width("80%")
.margin({top:50})
.onChange(value=>{
//获取文本框的值
this.uname=value;
})
TextInput({
placeholder:'请输入密码:'
}).type(InputType.Password)
.width("80%")
.margin({top:50})
.onChange(value=>{
//获取文本框的值
this.passwd=value;
})
Button("确定").width("50%").margin({top:50})
.onClick(e=>{
AlertDialog.show({
title:'接收的信息',
message:"姓名:"+this.uname+"\n密码:"+this.passwd,
primaryButton:{ value:'确定', action:()=>{ console.log('primaryButton确定') } }, secondaryButton:{ value:'取消', action:()=>{ console.log("secondaryButton事件") } }
});
})
}
}.width("100%")
.height("100%")
}
}
|
4.7.2.轮播图组件Swiper
接口
Swiper(controller?: SwiperController)

示例:
class MyBannerDataSource implements IDataSource { private banners:Array<string>=['/pages/images/banner1.png', '/pages/images/banner2.png', '/pages/images/banner3.png', '/pages/images/banner4.png', '/pages/images/banner5.png' ] private lisner: DataChangeListener unregisterDataChangeListener(listener: DataChangeListener): void { } registerDataChangeListener(listener: DataChangeListener): void { this.lisner=listener; } getData(index: number) { return this.banners[index]//获取索引位置处的元素值 } totalCount(): number { return this.banners.length; } }
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State uname:string='';
@State passwd:string='';
@State bannerdata:MyBannerDataSource=new MyBannerDataSource();
build() {
Column(){
Column(){
//准备放置轮播图
Column(){
Swiper(){ LazyForEach(this.bannerdata,(item,index)=>{ Image(item) .objectFit(ImageFit.Fill) .width("100%") .height("20%")
}) } .autoPlay(true)//自动滚动 .interval(5000)//5秒轮播一下 .indicator(true)//指示器显示 .loop(true)//重复轮播 .duration(1000)//延时1秒钟 .itemSpace(5)
}
Text("用户登录").margin({top:50})
TextInput({
placeholder:'请输入姓名:'
})
.width("80%")
.margin({top:50})
.onChange(value=>{
//获取文本框的值
this.uname=value;
})
TextInput({
placeholder:'请输入密码:'
}).type(InputType.Password)
.width("80%")
.margin({top:50})
.onChange(value=>{
//获取文本框的值
this.passwd=value;
})
Button("确定").width("50%").margin({top:50})
.onClick(e=>{
AlertDialog.show({
title:'接收的信息',
message:"姓名:"+this.uname+"\n密码:"+this.passwd,
/*confirm:{
value:'确定',
action:()=>{
console.log("确定")
}
},
cancel:()=>{
console.log("取消")
}*/
primaryButton:{
value:'确定',
action:()=>{
console.log('primaryButton确定')
}
},
secondaryButton:{
value:'取消',
action:()=>{
console.log("secondaryButton事件")
}
}
});
})
}
}.width("100%")
.height("100%")
}
}
|
4.8.鸿蒙的网络访问axios
4.8.1.安装文件位置: 总目录的oh-package.json5文件

dependencies:生产环境–上线运行时候必须需要的包
devDependencies:开发环境–开发适合为了方便提高效率的包。
oh-package.json5(不是entry下的文件)文件内容如下:
{
"name": "prjhmday11",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
},
"devDependencies": { "@ohos/hypium": "1.0.6" }
}
|
包管理工具
OHPM CLI 作为鸿蒙生态三方库的包管理工具,支持OpenHarmony共享包的发布、安装和依赖管理。
下载开发工具的时候会装一个ohpm的软件,就是这个。【下载地址】
配置环境变量
在命令行运行一下 ohpm -v。
如果已经安装但报下面错,说明需要配置环境变量。


重新启动项目,就可再次看到是可以的

安装第三方包
ohpm常见命令

如果不知道需要什么包,包的名字,可以在官网查看
安装一个http请求的axios试试
ohpm install @ohos/axios

oh-package.json5
{
"name": "prjhmday11",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
"@ohos/axios": "^2.2.4"
},
"devDependencies": {
"@ohos/hypium": "1.0.6"
}
}
|

在进行网络请求前,您需要在module.json5文件中申明网络访问权限。

Demo,在index.ets获取新浪最新头条。
import axios from '@ohos/axios'
interface ListType {
hotValue: string,
index: number,
link: string,
title: string
}
@Entry
@Component
struct Index {
@State ListData: ListType[] = []
build() {
Column() {
Row(){
Text('获取新浪头条:')
Button('请求').onClick(() => {
axios.get('https://api.codelife.cc/api/top/list?lang=cn&id=KqndgxeLl9').then(res => {
console.log(res.data.data[0])
this.ListData = res.data.data
})
})
}
Divider()
List({space:20}){
ForEach(this.ListData,item => {
ListItem(){
Row() {
Text(`${item.index}.${item.title}`)
Text(item.hotValue).fontWeight(FontWeight.Bold)
}
.width('100%')
.backgroundColor('#fff3a4b1')
.padding(10)
.borderRadius(8)
.justifyContent(FlexAlign.SpaceBetween)
}
// .margin({
// left:10,right:10
// })
},item => item.index)
}
}
}
}
|

4.9.web组件
承载网页的容器,可以在Web组件中打开网络请求的网页内容,在鸿蒙的手机端进行呈现。
4.9.1.Web组件详解
HarmonyOS中的Web组件是一种基于Web技术的组件,可以在HarmonyOS应用程序中嵌入Web内容。通过使用Web组件,开发人员可以将Web页面或应用程序嵌入到HarmonyOS应用程序中,实现更丰富的用户界面和功能。
Web组件提供了一系列的API和工具,开发人员可以使用这些API和工具来控制和操作内嵌的Web页面。例如,开发人员可以使用JavaScript和CSS来操作和样式化Web页面的元素,还可以使用HTML5的各种功能来实现各种交互和媒体功能。网页中的所有标签、样式和js代码都能在Web组件中使用。
Web组件还支持与HarmonyOS应用程序的其他部分进行通信和交互。开发人员可以使用JavaScript和HarmonyOS的API来实现应用程序的功能,例如访问设备的传感器、调用系统的功能等。此外,Web组件还可以通过与应用程序的其他组件进行交互来实现更复杂的功能,例如在应用程序的其他组件中显示Web页面的内容、发送和接收消息等。

4.9.2.使用Web组件加载页面
1.配置权限module.json5或者config.json中配置
"requestPermissions": [
{
"name": "ohos.permission.INTERNET" // 使用网络权限
}
] |

2.加载页面
引入:import web_webview from '@ohos.web.webview'
创建WebController对象
webController: web_webview.WebviewController =new web_webview.WebviewController()
使用控制器加载页面的方法:
this.webController.loadUrl('blog.csdn.net/aa2528877987');
创建Web组件,用于接收网页信息
Web({src:’默认的url地址’,controller: this.webController})
3.示例如下
打开应用,默认是百度,从文本框输入网址后,点击确定按钮后,获取文本框中输入的网址信息在Web组件中呈现
import web_webview from '@ohos.web.webview'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State url:string='https://www.baidu.com'
//定义webController
@State webController:web_webview.WebviewController=new web_webview.WebviewController()
build() {
Column(){
Column(){
Row(){
//用于输入网址的文本框
TextInput({
placeholder:'请输入要访问的网址'
}).width("80%")
.onChange(value=>{
this.url=value;//获取文本框中输入的网页地址
})
//点击确定按钮以后,准备接收网址的信息,传递给webController进行处理
Button("确定").width("20%")
.onClick(e=>{
this.webController.loadUrl(this.url)//使用控制器加载网页地址
})
}
//默认要加载的页面为baidu
Web({src:this.url,controller:this.webController})
.imageAccess(true)//允许自动加载图片资源
.javaScriptAccess(true)//是否允许执行JavaScript脚本
.mixedMode(MixedMode.All)//设置是否允许加载超文本传输协议(HTTP)和超文本传输安全协议(HTTPS)混合内容,默认不允许加载HTTP和HTTPS混合内容。
.horizontalScrollBarAccess(true)//设置是否显示横向滚动条,包括系统默认滚动条和用户自定义滚动条
.verticalScrollBarAccess(true)//设置是否显示横向滚动条,包括系统默认滚动条和用户自定义滚动条
.initialScale(100)
}
}
}
}
|

在文本框输入网址,点击确定,查看内容

五.使用鸿蒙元服务构建生肖命理的小程序
5.1.创建鸿蒙的元服务项目


5.2.整理需要的资源
轮播图资源和生效图片和命理描述。
5.2.1.准备轮图的代码实现:
//创建轮播图的数据源类
class MyBannerDataSource implements IDataSource {
private banners:Array<string>=['/pages/images/sxbanner1.png',
'/pages/images/sxbanner2.png','/pages/images/sxbanner3.png'];
private lisner: DataChangeListener;
unregisterDataChangeListener(listener: DataChangeListener): void {
}
registerDataChangeListener(listener: DataChangeListener): void {
this.lisner=listener;
}
getData(index: number) {
return this.banners[index];
}
totalCount(): number {
return this.banners.length;
}
} //==========================================
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State bannerDataSource:MyBannerDataSource=new MyBannerDataSource();
build() {
Column(){
//===放置广告轮播图======================= Column(){ Swiper(){ LazyForEach(this.bannerDataSource,(item,index)=>{ Image(item) .objectFit(ImageFit.Fill) .width("100%") .height("20%") }) }.autoPlay(true)//自动滚动 .interval(5000)//5秒轮播一下 .indicator(true)//指示器显示 .loop(true)//重复轮播 .duration(1000)//延时1秒钟 .itemSpace(5) } //======================================
//======放置生肖列表=======================
//======================================
}
}
}
|
5.2.2.使用列表组件呈现十二生肖图片
定义十二生肖数组,包括,图片、标题和内容描述
使用列表组件呈现生肖的列表视图
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
class MyBannerDataSource implements IDataSource {
private banners:Array<string>=['/pages/images/sxbanner1.png',
'/pages/images/sxbanner2.png','/pages/images/sxbanner3.png'];
private lisner: DataChangeListener;
unregisterDataChangeListener(listener: DataChangeListener): void {
}
registerDataChangeListener(listener: DataChangeListener): void {
this.lisner=listener;
}
getData(index: number) {
return this.banners[index];
}
totalCount(): number {
return this.banners.length;
}
}
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
//定义广告轮播数据源对象
@State bannerDataSource:MyBannerDataSource=new MyBannerDataSource();
//定义十二生肖数组
@State shengxiaoarray:Array<object>=[
{ 'sximage': $rawfile("shu.png"),'title':'子鼠','jianjie':'食伤旺日,福禄好运,运势极强。','note':'属鼠人来到2024年,由于自己的地支子与流年地支辰为半合,原则上关系友好,加上“申子辰”(猴、鼠、龙)又属三合生肖,有互利互旺作用,所以新一年做事将会较为顺遂,而属猴人于龙年更是自己的贵人,所以不妨多聆听对方意见或寻求对方协助解决疑难。不过,半合之年部分人也会面临变化,运势较为反覆,仍然需要谨慎提防。吉星方面,龙年只有一颗“将星”进驻,此星代表将军统领下属及调兵遣将,有坚毅不屈、发奋图强之意,若任职大机构、政府部门或纪律部队者,新一年有望发挥领导才能,兼有不俗升迁机会。不过,此星对从商者助力一般,龙年需要带领下属感觉较为艰辛,保持默默耕耘、不问回报的态度为佳,所以不宜将目标订得太高。属鼠人今年可随身佩戴一个玄武献瓶吉宏吊坠作为2024年吉祥饰物。另外,新一年也有“白虎”、“披头”、“飞帘”及“天雄”凶星入驻,难免会对运势带来负面影响。“白虎”代表蛮不讲理、脾气刚烈的女性,若属鼠人的直属上司是女性,新一年要有心理准备对方将会诸多挑剔,需要以无比耐性应对。此星也有“马路如虎口”之意,属鼠人要时刻注意道路安全,提防轻微血光之灾。“披头”则较为冲击家宅运,龙年要多花时间关心长辈健康。“披头”也有“披头散发”之意,龙年改变形象前需要特别小心,容易因为不被他人接纳而影响人际关系。“飞帘”则属是非口舌的凶星,新一年将会有较多小人及琐碎问题需要处理,让属鼠人颇为烦心。' },
{ 'sximage': $rawfile("niu.png"),'title':'丑牛','jianjie':'六合贵人,大吉大利,做事顺利。','note':'属牛人踏入2024年属“破太岁”,破即人际关系遭到破坏,虽然其冲击力量不及本命年及冲太岁强大,但做事难免会遇上繁琐的困扰,较影响情绪,甚至会因为无心之失而得罪权贵,需要小心迎接挑战。好在2024年也有颇多吉星进驻,为属牛人的运势增添助力。“玉堂”代表金玉满堂,新一年财运理想,有望有不俗进帐。“天德”是上天之德,“福星”及“八座”则代表幸运,2024年做事虽然不算一帆风顺,但是遇上困难仍能凭运气或贵人而逢凶化吉,所以整体仍算有所进步。不过,2024年也有一组凶星入驻,“卷舌”即是非口舌,新一年人际关系欠佳,容易得罪重要人物,需要谨言慎行。属牛人今年可随身佩戴一个鼠鹿护岁吉宏吊坠作为2024年吉祥饰物。“绞煞”代表纠缠不清、拖拖拉拉的关系,容易因为锋芒太露而招人妒忌。“寡宿”顾名思义就是孤枕独眠,属牛的女性2024年特别容易觉得伴侣不够谅解自己,而此星也会冲击另一半健康,因此也要多关心陪伴对方。至于“披麻”及“扳鞍”则不利家宅,2024年要多花时间关心长辈健康,遇有不适应立即陪同求医。' },
{ 'sximage': $rawfile("hu.png"),'title':'寅虎','jianjie':'食神制煞,好运势来自于努力的付出。','note':'属虎人进入2024年与太岁无冲无合,原则上运势的稳定性将会更高。不过,由于新一年进驻的吉星不算多,而且力量主要集中在事业发展上,所以其他范畴助力较少。另外,自古有龙争虎斗之说,属虎人在2024年容易与他人作比较,感觉竞争较大及易有精神压力,需要调节心态' },
{ 'sximage': $rawfile("tu.png"),'title':'卯兔','jianjie':'贵人和合,好运相随,求谋顺心。','note':'属兔人在2024年间的财运欠佳,生活质量有所下滑,工作无法顺心如意的完成,会被小人所陷害,工资收入锐减,上班族每个月的工资收入少,只能够维系日常的生活开支,家里有了大事,需要为了钱去感到担忧,还需要借钱过日子。属兔人需要开源节流,不要随意花费钱财,也不要有攀比心理,不要像往日一样大手大脚的花钱,会影响财运的发展。' },
{ 'sximage': $rawfile("long.png"),'title':'辰龙','jianjie':'丑未相冲,运势低迷,一切都要慎重。','note':'2024年是属龙人本命年犯太岁之年,再加上辰辰刑出现“刑太岁”,双重夹击之下运势难免起伏。所谓“太岁当头坐,无喜必有祸”,若新一年有结婚、添丁、置业或创业等重大喜事,则可将犯太岁的冲击减到最低,否则就要做好迎接充满挑战的心理准备。好在龙年有“岁驾”吉星,此星象征古时皇帝坐轿出巡、光芒万象的场面,因此新一年事业还有望提升,但也会因座驾而要额外花费。而“华盖”则是帝皇出行时所用的绸伞,代表艺术才华出众,从事创作者将有不俗发展。不过,此星也代表高高在上、孤芳自赏,不利人缘及桃花,容易因为恃才傲物而影响人际关系。属龙人本命年可随身佩戴一个麟凤赐福吉宏吊坠作为2024年吉祥饰物。另外,龙年也有“太岁”及“剑锋”一组不利健康的凶星,必须提防受金属所伤或开刀破相,驾驶者要时刻注意道路安全,工作需要接触机械者也要格外留神,至于其他属龙人则不宜参与高危的户外活动,凡事安全为上。“三刑”及“黄幡”则会冲击家宅,新一年要多关心长辈健康,遇有不适应立即陪同求医。由于龙年有两颗帝皇吉星拱照,事业发展算是颇为称心如意,尤其大利文艺领域者。不过,2024年始终属犯太岁之年,运势的不稳定因素较多,所以投资方面必须保守,只宜选择中长线项目,不宣涉猎高风险的投机炒卖。情侣也要果断决定二人关系能否更进一步,以免陷入分离运势。' },
{ 'sximage': $rawfile("she.png"),'title':'巳蛇','jianjie':'贵人入命,有人相助,好运相随。','note':'属蛇人进入2024年与太岁无冲无合,整体运势相对平稳。甲辰年之后的乙巳年是属蛇人的本命年,届时运势会有较大起伏,而部分人于年末已开始受影响,所以需要提前作好准备。好在2024年仍有不少吉星拱照,为属蛇人的运势加添助力。“天喜”是喜事连连的桃花星,新一年将有结婚、添丁,甚至双喜临门的事,尤其2025年是本命年,所以于2024年筹备婚礼、蛇年落实举行或于2024年结婚、蛇年添丁也相当合适,有望主动应验运势。“天厨”则代表新一年应酬活动频繁,有望扩阔社交圈子认识新朋友。不过,由于人缘畅旺,已有伴侣者不宜对异性太热情,以免惹误会引发三角关系。“文昌”乃有利读书、考试的吉星,对任职大机构或文职者最有助力,若公司内部有升级考核不妨主动参加,有利获取好成绩。属蛇人今年可随身佩戴一个双豹采芝吉宏吊坠作为2024年吉祥饰物。此外“天空”代表天马行空,从事创作者灵感不绝,常以文件处理公务者也有不俗发挥。“太阳”则是男性贵人,若业务以男性顾客为主,如销售汽车、音响或模型等,更易获得客人支持,若上司或老板是男性也有提拔作用。此星也有光照远方之意,打算拓展海外市场者可落实执行,也可出差走动带旺运势。' },
{ 'sximage': $rawfile("ma.png"),'title':'午马','jianjie':'煞印相生,办事别拖泥带水为好。','note':'属马人在2023年兔年犯破太岁,“破”即人际关系的破败,无论事业或情绪都比较受影响。进入2024年龙年因与太岁无冲无合,运势将会较为稳定,加上人际运有进步,整体有望重上轨道。不过,今年只有一颗“天解”吉星的助力,而且此星代表需要经历波折才能成功,并非完完全全的吉星,意味着做事仍会遇到阻碍,过程中困难较多,好在只要亲力亲为、多花时间耐心处理,最终仍可水到渠成。另外,此星亦有解除盟誓及分离之意,若有婚约在身者,龙年需要特别小心维系感情,以免关系出现变化。此星不太利感情,但反映在人际关系上还算正面:之前的误会有望冰释前嫌,人际运有所好转。至于财运亦算缓慢向前,但仍需辛苦得财。龙年亦有一组凶星临门,属马人需要特别注意。“丧门”、“地丧”、“血刃”及“浮沉”比较冲击家宅运,新的一年里宜多关心父母、祖父母等长辈健康;“浮沉”亦代表水险,龙年不宜参与冲浪、潜水等水上运动,即使必须参加,也要有专业教练结伴同行,不宜独游,以免乐极生悲。属马人今年可随身佩戴一个白泽迎鸿吉宏吊坠作为2024年吉祥饰物。此星亦代表起伏较大,反映在财运之上有时好时坏之势,因此从商者更要未雨绸缪,反映在感情之上则代表忽冷忽热,心态较为矛盾,需要多花时间维系。' },
{ 'sximage': $rawfile("yang.png"),'title':'未羊','jianjie':'六合贵人,办事顺利,利于做大事。','note':'属羊人在2023年因轻微合太岁,故部分人已经历了变化或开展新合作,至于实际走势好坏,则要根据个人出生月份来确定。来到2024年既无冲也无合,整体运势相对平稳,但因为甲辰年行木、土运,而秋、冬两季出生的人命格更利好这类元素,故本年度的稳定性将会更高。 好在无论是任何季节出生,属羊人在龙年仍有一组吉星拱照,为运势增添助力。“天乙”属强而有力的贵人星,本年度无论家人、朋友、同事或前辈均对自己爱护有加,做事如虎添翼,从商者有望获得原有客户支持,亦可凭人脉网络而开拓新客源,事业及财运均有收获。至于“太阴”则是缓慢的财星,本年度财运走势稳定,不属于起伏较大的横财。而此星亦代表女性长辈,上班族若直属上司是女性,龙年将有被提拔的可能,又或经营的生意以女性顾客为主,如销售女士服装、美容、化妆或珠宝首饰等,业绩也会受带动而有所提升。此吉星套用在感情之上亦颇为正面,尤其单身男士异性缘旺盛,有望结识条件不俗的对象,但对方可能比自己稍为年长,若钟情成熟型或不介意年龄差距者,不妨多加观察了解,有望开展一段甜蜜的“姐弟恋”。属羊人今年可随身佩戴一个飞狮镇塔吉宏吊坠作为2024年吉祥饰物。 不过,龙年仍有“贯索”及“勾绞”凶星入主,代表关系上纠缠不清,容易与人有金钱纠葛,加上“贯索”本身带有不和及互相指责的意思,建议本年度应避免与人合作投资,即使坚持合作也要先签订条款及细则,与生意伙伴或客户的帐目往来要清楚分明,以免日后双方出现争议或误会而添烦恼,甚至因财失义而有反目成仇的情况。' },
{ 'sximage': $rawfile("hou.png"),'title':'申猴','jianjie':'泄秀灵秀,魅力无限,适合交际。','note':'在12生肖中,猴龙鼠属三合生肖,踏入2024年龙年,由于本命生肖与流年太岁关系友好,所以属猴人本年度做事将会较为顺遂,有望得到贵人扶持,无论财运、感情运及人际关系各方面也有进步。若龙年遇上麻烦阻滞,不妨向属鼠的朋友寻求协助,对方有望起通关作用而令问题迎刃而解。不过,2024年之后的蛇年是属猴人的合太岁年份,而合太岁与冲太岁相似,运势难免会有较多变数,甚至会各走极端,所以必须在年尾提早部署,尤其跨年项目更要特别谨慎处理,以免踏入蛇年遇上突如其来的变化而有亏损。 虽然龙年只有“三台”一颗吉星进驻,但此星力量充足,具有步步高升之意,作用于任何领域都有一定助力。“三台”有利事业升迁及考试运,本年度事业发展有望更上一层楼;财运也会有一定进账,从商者业绩有所提升,盈利增长。此星作用在感情方面亦可见缓慢进步,情侣沟通了解增多,关系可更进一步。至于单身者可于职场或老朋友的社交聚会当中遇上有好感的异性,彼此见面及相处机会增加,有望循序渐进建立感情。属猴人今年可随身佩戴一个吉蛇攀象吉宏吊坠作为2024年吉祥饰物。不过,本年度亦有“官符”凶星入主,属猴人有可能因为官非诉讼而破财,从商者草拟或签署文件、合约前要厘清条款细则,遇到疑问应向专业人士请教。期间不宜作借贷担保,即使是熟悉的客户,也不宜答应对方赊款、赊货,以免对方陷入财因而影响自己,甚至最后需要对簿公堂。至于“五鬼”代表精神紧张、疑神疑鬼,属猴人本年度容易对伴侣有所猜疑,建议双方需要多花时间沟通,了解对方的想法,以免影响感情。' },
{ 'sximage': $rawfile("ji.png"),'title':'酉鸡','jianjie':'逢冲之日,不利友情,注意情感纠纷。','note':'经历过2023年的冲太岁年份,相信不少属鸡人已出现了事业、感情或家宅上的变化,来到2024年龙年则属合太岁之年,运势容易走向极端,当中约七成人会循序渐进向上,但也有三至四成人会波折重重,所以仍要步步为营。合太岁之年运势难免较为动荡,而实际走向则要参考之前一年的经历。若兔年曾有结婚、添丁、置业或创业等喜事,则龙年有望延续喜庆运势。若兔年曾经历分手、离婚,也有望重新开始,甚至会有闪婚的可能。相反,若兔年没有重大突破,2024年来临之时就要特别谨慎提防。 话虽如此,属鸡人在本年度仍可得到吉星加持。“月德”是慈祥和悦的贵人星,有望凭人脉逢凶化吉;“唐符”则代表权力与威望,对事业及财运均有助力。另外一颗“地解”意味着田宅变化,龙年有可能要搬迁、装修或离开原住地发展。属鸡人今年可随身佩戴一个天禄登峰吉宏吊坠作为2024年吉祥饰物。而“岁合”属于半颗桃花星,单身人士感情多姿多采,但受到另一颗桃花星“咸池”影响,关系较为短暂及不实在,已婚人士不宜对人太热情,以免引发三角关系。另外,相合之年容易有新的合作或投资机遇,但吉中藏凶,容易有意料之外的结果,加上有代表轻微破财的“小耗”凶星入命,落实前必须要多作分析研究,采取小试牛刀的方式试行,并要提高情商,才能接受当中的变动。' },
{ 'sximage': $rawfile("gou.png"),'title':'戌狗','jianjie':'逢害之日,需要防范顺势不利。','note':'属狗人踏入2024年冲太岁之年,虽然运势未必一面倒,但难免会存在较多变动;而且辰戌冲属于“天罗地网”,其冲击力量相比起其他生肖的相冲更大,部分属狗人可能在兔年年底就已经感受到了相冲的影响力,因此必须多作准备,迎接运势反复多变的一年。所谓“一喜挡三灾,无喜是非来”、“太岁当头坐,无喜必有祸”,若本年度有结婚、添丁、置业或创业等喜事,宜积极推进,则可将相冲力量减到最低。至于没有喜事的人,则要提防感情迎来关口年,与伴侣有可能出现分分合合。部分属狗人亦会蠢蠢欲动,想在事业上寻求改变,包括离开原有岗位,或有创业念头等等,落实前必须要以谨慎保守为大前提,不宜涉及大额投资,以免因为决策错误而损失惨重。属狗人今年可随身佩戴一个虎马保岁吉宏吊坠作为2024年吉祥饰物。好在2024年仍有“国印”吉星入主,此星代表帝王掌握权力的帅印,本年度的权力地位有所提升,事业方面会有出色表现,也有更多出差或升迁的机会,值得好好把握。不过,龙年亦有“栏杆”凶星阻碍运势,此星代表做事将遇上麻烦阻滞,容易一波三折,属狗人需要务必耐心克服困难。“岁破”及“豹尾”则是人际关系上的破坏,本年度容易得罪权贵,甚至会有可能被小人反噬,待人接物宜特别谦虚低调。加上有代表破财的“大耗”凶星来袭,必须更加谨慎理财,不宜涉猎高风险的短炒投机项目,以免入不敷出。' },
{ 'sximage': $rawfile("zhu.png"),'title':'亥猪','jianjie':'印比之日,努力学习别人的优点,自己必然能受益','note':'属猪人在2024年龙年,与流年太岁无冲无合,加上有一组强而有力的吉星加持,故整体运势算是颇有进步。不过,龙年之后的蛇年便是冲太岁之年,运势难免会反复起伏,所以属猪人必须在龙年年底开始提早部署,尤其若有牵涉跨年的投资项目,要更加谨慎,建议先行结算赚取本金,以免犯太岁之年来临,出现突如其来的变化。 进入2024年,属猪人喜获“紫微”、“龙德”吉星眷顾,做事将会如虎添翼,尤其个人领导才能得以彰显。而且“紫微”及“龙德”属得力的贵人星,即使遇上麻烦阻滞,也可逢凶化吉,有望借助人脉关系支持,事业有所提升,财运方面也可能凭借人脉获取更多内部消息,而洞悉先机赚取收入。另外,2024年还有“红鸾”进驻,此吉星除了有利桃花外,对人际关系也大有裨益,从事中介、销售等以人为本的工作,本年度有望得到客户鼎力支持,任职大机构或文职者与同事的关系亦有好转,不妨积极把握。“红鸾”吉星还会令属猪人魅力四射,单身人士有望结识合眼缘对象,甚至有闪婚的可能。不过,本年度也有“暴败”凶星来袭,此星代表财运起伏较大,容易有三更穷、五更富的情况,经商人士必须开源节流,未雨绸缪提前准备一笔应急钱,以备不时之需。投资方面也要见好即收,不宜进行高风险的投机炒卖。属猪人今年可随身佩戴一个鹤鲤折桂吉宏吊坠作为2024年吉祥饰物。而“暴败”反映在感情之上,也有热情减退、忽冷忽热之意,与伴侣的关系较为不稳定,需要多花时间维系。至于“天厄”及“亡神”则是出门后的小意外、小惊吓,包括行李或航班延误、目的地的天气变化或财物遗失等,出门在外必须注意人身安全,或可预先购买旅游保险,以策万全。' },
]
build() {
Column(){
//===放置广告轮播图=======================
Column(){
Swiper(){
LazyForEach(this.bannerDataSource,(item,index)=>{
Image(item)
.objectFit(ImageFit.Fill)
.width("100%")
.height("20%")
})
}.autoPlay(true)//自动滚动
.interval(5000)//5秒轮播一下
.indicator(true)//指示器显示
.loop(true)//重复轮播
.duration(1000)//延时1秒钟
.itemSpace(5)
}
//======================================
//======放置生肖列表=======================
Column(){
List(){
ForEach(this.shengxiaoarray,(item,index)=>{
ListItem(){
Column(){
Row(){
Image(item.sximage)
.objectFit(ImageFit.Cover)
.width("40%")
.height(100)
Column(){
Text(item.title).fontSize(30).margin({left:20})
Text(item.jianjie).width("50%").margin({left:20,top:10})
Button("查看详细")
.width("20%")
.height("5%")
.backgroundColor('#F6D48D')
.margin({left:100})
.onClick(e=>{//按钮的事件处理
AlertDialog.show({
title:item.title,
message:item.note,
confirm:{
value:'确定',
action:()=>{
console.log("确定")
}
}
});
})
}.margin({top:10})
}.padding(5)
}
}
})
}
}
//======================================
}
}
}
|


5.3.使用组件化模块构建生鲜超市首界面
5.3.1.对首界面各个容器进行布局
按照banner\导航、推荐、产品列表和底部栏进行布局

5.3.2.构建外部组件
1.准备广告banner栏的外部组件

bannercompoent.ets
import { BannerBean } from '../../../commons/bannercompoent'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column(){
//放置轮播图
Column(){
BannerBean()//调用外部的广告轮播组件进行呈现
}.width("100%").height("20%")
//放置导航
Column(){
}.width("100%").height("5%").backgroundColor("#ffffcc")
//放置推荐的菜品10个
Column(){
}.width("100%").height("20%").backgroundColor("#FFFFEE")
//放置菜品列表
Column(){
}.width("100%").height("45%").backgroundColor("#FFCCCC")
//放置底部导航
Column(){
}.width("100%").height("15%").backgroundColor("#CCFFCC")
}
}
}
|
2.导航栏组件的构建navcompoent.ets

navcompoent.ets
@Component
export struct NavBean{
@State titles:Array<string> =['水果','蔬菜','干果','粮油','辅食','日用','肉食','熟食','香料','香烟','酒类']
build(){
Column(){
List({space:5}){
ForEach(this.titles,(item,index)=>{
ListItem(){
Text(item).fontSize(18).fontWeight(FontWeight.Bold).lineHeight(30)
.backgroundColor("#CCFFCC")
Divider().vertical(true).margin({left:60}).color("#95D4F7").strokeWidth(1)
}
})
}.listDirection(Axis.Horizontal)//水平放置导航
}.width("100%").width("100%")
}
}
|
3.商品推荐的组件构建toptencompoent.ets

import { BannerBean } from '../../../commons/bannercompoent'
import { NavBean } from '../../../commons/navcompoent'
import { TopTen } from '../../../commons/toptencompoent'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column(){
//放置轮播图
Column(){
BannerBean()//调用外部的广告轮播组件进行呈现
}.width("100%").height("20%")
//放置导航
Column(){
NavBean()
}.width("100%").height("5%").backgroundColor("#ffffcc")
//放置推荐的菜品10个
Column(){
TopTen().margin({top:10})
}.width("100%").height("20%").backgroundColor("#FFFFEE")
//放置菜品列表
Column(){
}.width("100%").height("45%").backgroundColor("#FFCCCC")
//放置底部导航
Column(){
}.width("100%").height("15%").backgroundColor("#CCFFCC")
}
}
}
|
4.商品列表组件productlistcompoent.ets

productlistcompoent.ets
@Component
export struct ProductList{
@State productlist:Array<object>=[
{'tite':'白菜','price':'¥4.5','imgsrc':$rawfile('baicai.jpg'),'note':'xxxx'},
{'tite':'车厘子','price':'¥7.8','imgsrc':$rawfile('chelizi.jpg'),'note':'xxxx'},
{'tite':'果脯','price':'¥8.2','imgsrc':$rawfile('guopu.jpg'),'note':'xxxx'},
{'tite':'核桃','price':'¥7.7','imgsrc':$rawfile('hetao.jpg'),'note':'xxxx'},
{'tite':'枇杷','price':'¥8','imgsrc':$rawfile('pipa.jpg'),'note':'xxxx'},
{'tite':'芒果干','price':'¥9','imgsrc':$rawfile('mangguogan.jpg'),'note':'xxxx'},
{'tite':'芹菜','price':'¥2.2','imgsrc':$rawfile('qincai.jpg'),'note':'xxxx'},
{'tite':'柿子饼','price':'¥4.5','imgsrc':$rawfile('shizibing.jpg'),'note':'xxxx'},
{'tite':'桃子','price':'¥8.3','imgsrc':$rawfile('taozi.jpg'),'note':'xxxx'},
{'tite':'提子','price':'¥12','imgsrc':$rawfile('tizi.jpg'),'note':'xxxx'},
{'tite':'西红柿','price':'$4.5','imgsrc':$rawfile('xihongshi.jpg'),'note':'xxxx'}
]
build(){
Column(){
List({space:10}){
ForEach(this.productlist,(item,index)=>{
ListItem(){
Column(){
Row(){
Image(item.imgsrc).objectFit(ImageFit.Fill).width(100).height(60)
.borderRadius(10)
Column(){
Text(item.tite).fontSize(20).fontWeight(FontWeight.Bold)
Text(item.price).fontSize(16).margin({top:10})
Button("订购").width(70).fontSize(10).height(20).margin({left:50,top:10})
}.margin({left:10})
}
}.backgroundColor("#F9F9F9").width("90%").height("30%").borderRadius(10)
}
})
}
}
}
}
|
5.主页面index.ets的调用方式
import { BannerBean } from '../../../commons/bannercompoent'
import { NavBean } from '../../../commons/navcompoent'
import { ProductList } from '../../../commons/productlistcompoent'
import { TopTen } from '../../../commons/toptencompoent'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Column(){
//放置轮播图
Column(){
BannerBean()//调用外部的广告轮播组件进行呈现
}.width("100%").height("20%")
//放置导航
Column(){
NavBean()
}.width("100%").height("5%").backgroundColor("#ffffcc")
//放置推荐的菜品10个
Column(){
TopTen().margin({top:10})
}.width("100%").height("20%").backgroundColor("#FFFFEE")
//放置菜品列表
Column(){
ProductList().margin({top:10,left:20})
}.width("100%").height("45%").backgroundColor("#FFCCCC")
//放置底部导航
Column(){
}.width("100%").height("15%").backgroundColor("#CCFFCC")
}
}
}
|

所有评论(0)