HarmonyOS应该如何上手?有没有实操项目可供入门?HarmonyOSCodeLab栏目致力于挖掘生动有趣的案例,用浅显易懂的文字,简单易上手的代码,呈现HarmonyOS开发的多样性,让你一看就懂,一敲就会!
本期就让我们从一个简易的HarmonyOS购物应用入手,通过5个可视页面来为大家介绍15个JS常用组件,看看HarmonyOS是如何通过多种组件,帮助开发者减少开发量,让开发者只需关注实现逻辑的。事不宜迟,我们马上开始。
【请注意】本Demo只为展现多种JS组件用法,购物应用仅为场景演示,并非完整应用,欢迎各位开发者根据自己的业务场景进行完善哦~
首先来看一下本Demo中涉及的15个组件,包括:搜索框组件(search)、页签组件(tabs)、列表组件(list)、图片组件(image)、分隔器组件(divider)、交互式组件(input)、滑动容器(swiper)、跑马灯组件(marquee)、自定义弹窗容器(dialog)、滑动选择器组件(picker)、评分条组件(rating)、进度条组件(progress)、菜单组件(menu)、按钮组件(button)和图表组件(chart)。
再来看一下涉及的5个可视页面,分别为商品陈列页面、购物车页面、我的信息面,商品详情页面,商品数据分析页面。其中,前3个页面的构建将在homepage代码文件中展现。商品详情页将在shoppingDetailsPage代码文件中构建,商品数据分析页面将在viewChart代码代码文件中呈现,更多为了展示按钮组件和图表组件的使用方式。
我们用一个表格来让大家一目了然:
在正式开始敲代码之前,开发者们需要先下载安装Huawei DevEco Studio,如果对于
这个流程不甚熟悉,可以参照官网的教程操作。
Huawei DevEco Studio安装指南:
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415
请注意,本次Codelab针对的是步骤拆解和重点讲解,限于篇幅原因不会展示完整代码
工程的代码结构
先让我们来了解一下工程的代码结构,这里我们提取几个重要信息跟大家说明一下:
- entry/src/main/js/default/common 文件夹存放一些公共的资源,本次的图片内容皆存放在此。
- entry/src/main/js/default/pages 文件夹存放 HarmonyOS JS的代码文件,包含css、hml、js三类文件,这里我们创建了homepage、shoppingDetailsPage、viewsChart。
- entry/src/main/config.json:配置文件
页面构建及组件使用详解
接下来,我们就可以编写css、hml、js代码了。
我们先来明确一下5个可视页面的逻辑。Demo从主应用界面(Demo直接展现的页面)
菜单栏可划分为三个可视页面,分别为商品陈列页面、购物车页面、我的信息页面,这三个可视页面的构建都在homepage中,当用户点击商品陈列页面中的商品可跳转到商品详情页(为了方便演示均采用同一商品详情页),该可视页面在shoppingDetailsPage中实现。此外,由商品详情页中的某个入口可跳转到商品数据分析页面,该页面在viewChart中编写。
下面我们将通过组件代码结合页面实现的部分,来为大家展示关键代码部分。
homepage代码文件
在本示例中,商品陈列页面、购物车页面、我的信息页面均在homepage代码文件中完成,每个可视页面均有不同的组件展现,下面我们来具体看一下。
- 商品陈列页面
在此可视页面中,用户可以通过搜索框搜索,或者直接在页面内浏览推荐商品。如果想要了解某个商品的详细信息,可以通过点击进入商品详情页查看。
这里我们将会用到:搜索框组件(search)、tab页签容器(tabs)、列表组件
(List)、图片组件(image)
搜索框组件(search)
搜索框组件用于提供用户搜索内容的输入区域。
在本示例中,search 组件中的hint属性囊括了搜索提示文字“寻找宝贝、店铺”,value用于搜索框搜索文本值,这里是一个固定值——手机,focusable确定当前组件是否可以获取焦点,本例中设置为true,可以实现用户点击时弹出,当用户在输入框内输入的值,发生变化的时候,会触发change事件,submit实现页面底部出现“搜索词+正在搜索中…”文字字样。
代码和图片示例如下:
<search hint="{{pageWord.searchKeyWord}}" value="{{pageWord.searchValue}}" focusable="true" @submit="submitColumn"> </search>
tab页签容器(tabs)
tabs是一个tab页签容器,tab-bar与tab-content均为其子组件,其中前者用于展示tab的标签区。后者用于展示tab的内容区。
官网链接:
在本示例中,搜索框下方“热销单品”、“精品推荐”、“智慧生活”、“年货节”等就用到了tab页签容器,组件中的index代表激活态,vertical代表内容排列方式,false为上下true为左右,这里采用的是上下,当点击或滑动标签时会触发change事件,标签兰下方的内容湖根据标签的变化而变化,当前的标签栏会显示红色,这样一个简单美观的标签栏就构造好啦。
而下面使用到了tabs的子组件tabs-bar和tab-content。tabs-bar中设置该组件的排列方式为横向排列,tabs-content用于展示tab的内容区,其中的scrollable,用于实现滑动切换页签。
当然,开发者可以根据需要 改变tabs页签的页面内容、逻辑以及样式。
代码和图片示例如下:
<tabs class="tabs" index="0" vertical="false" onchange="change"> <tab-bar class="tab-bar" mode="fixed"> <text class="tab-text" for="{{ item in titileList}}">{{ item }} </text> </tab-bar> <tab-content class="tabcontent" scrollable="true"> <div class="item-content" for="{{ item in contentList}}"> <list class="todo-wraper"> <list-item for="{{lists}}"> <div class="margin10" @click="detailPage"> <div class="todo-total"> <text class="todo-title"> {{$item.title}} </text> <text class="todo-content"> {{$item.content}} </text> <text class="todo-price"> <span> ¥ </span> <span> {{$item.price}} </span> </text> </div> <div class="width30"> <image src="{{$item.imgSrc}}" class="container-home-image"> </image> </div> </div> </list-item> </list> </div> </tab-content> </tabs>
列表组件(List)
list,即列表,包含一系列相同宽度的列表项。适合连续、多行呈现同类数据,例如图片和文本。list-item 是list的子组件,用来展示列表具体item。
官网链接:
在本示例中,商品页面宽度高度整齐的排列,就依托于list组件在.hml中声明以及在.css中进行样式设置。而list-item则展示
部分代码和图片示例如下:
<list class="todo-wraper"> <list-item for="{{lists}}"> <div class="margin10" @click="detailPage"> <div class="todo-total"> <text class="todo-title"> {{$item.title}} </text> <text class="todo-content">{{$item.content}} </text> <text class="todo-price"> <span> ¥ </span> <span> {{$item.price}} </span> </text> </div> <div class="width30"> <image src="{{$item.imgSrc}}" class="container-home-image"> </image> </div> </div> </list-item> </list>
图片组件(image)
Image,图片组件,在开发应用中,也是比较常见的一个组件,用来渲染展示图片。
官网链接:
在本示例中,商品的图片展示就是利用了图片组件来完成,其中src中是填写图片的路径。
部分代码和图片示例如下:
<image src="{{$item.imgSrc}}" class="container-home-image"> </image>
- 购物车页面
购物车页面让用户可以把选中的商品加入其中,并在其中选择想要的商品用于结算。在本例中为了便于大家理解,购物车中的商品已经锁定。这里我们将会用到分隔器组件(divider)和交互式组件(input)。
分隔器组件(divider)
分隔器组件(divider)用于分隔不同内容块/内容元素,可用于列表或界面布局。
官网链接:
在本示例中,多次使用到分隔器组件(divider),在这个页面中,我们仅做样式变化,但divider还可以使用vertical属性实现组件见的分割,比如在shoppingDetailPage中,我们使用该分割器实现评分条上“确认”和“取消”这两个按钮的分割。
该组件使用所在的购物车页面代码及图片如下:
<divider class="dialog-divider"> </divider>
交互式组件(input)
交互式组件(input)包括单选框,多选框,按钮和单行文本输入框,在本例中用于购物车产品的选择。
官网链接:
在本Demo中,我们多次用到该交互式组件。其中,在购物车页面中,input定义为多选框,用户可以选择自己喜欢的一个或多个商品进行结算,type="checkbox"类型定义为多选框 value是input组件的value值,在此地方是商品的价格 @change当多选框勾选状态发生变化时触发该事件
代码及图片如下:
<input type="checkbox" value="{{$item.price}}" @change="addShopping"> </input>
- 我的信息页面
我的信息页面布局,主要使用的是图片组件(image),用来呈现页面中的图标,使用方法与前面类似,这里就不多说。直接上代码和示例图片:
<div class="container-my-deals"> <text class="container-my-deals-text">{{pageWord.myDeals}}</text> <div class="container-my-deals-div"> <div class="container-my-deals-div-div" for="{{transaction}}"> <image src="{{$item.src}}" class="container-my-image"></image> <text class="container-my-text">{{$item.title}}{{$item.num}}</text> </div> </div> </div>
完成了上述三个可视页面的开发,我们接下来要开发商品详情页面。用户在商品陈列页面中点击任意商品即可跳转到该页面,此跳转动作在homepage的.js文件中实现。由于不属于组件内容,这里只简单显示代码:
detailPage() { router.push({ uri: "pages/shoppingDetailsPage/shoppingDetailsPage" }) },
shoppingDetailsPage代码文件
在本示例中,shoppingDetailsPage代码文件主要包含商品详情页面的构建。
1.商品详情页面
商品详情页面将会展示商品更加详细的信息,包括头部的滑动图片、价格、收货地址选择等。涉及到的组件包括:滑动容器(swiper)、跑马灯组件(marquee)、自定义弹窗容器(dialog)、滑动选择器(picker)、评分条(rating)、进度条组件(progress)和菜单组件(menu),下面我们来具体看一下。
滑动容器(swiper)
滑动容器,用户可以在swiper组件上进行滑动 左右切换图片,或者3s自动滑动一次。
官网链接:
在本示例中,通过图片轮播图的形式对商品的图片进行展示。其中,class="swiper"是构建swiper的样式,id="swiper"表示"swiper"是该组件的唯一标识,index显示当前容器的第几张图片,在本例中默认是从0开始,autoplay="true"表示开启图片自动循环播放,interval="3000"是每隔3S切换一次图片,indicator="true"启用导航点指示器,loop="true"开启循环轮播。digital="false",关闭数字导航点,当开发者以往显示数字的时候,就可以设置成true。
代码及图片示例如下:
<swiper class="swiper" id="swiper" index="0" autoplay="true" interval="3000" indicator="true" loop="true" digital="false"> <div class="swiperContent" for="{{ item in swiperList }}"> <image src="/common/computer/computer{{item}}.png"></image> </div> </swiper>
跑马灯组件(marquee):
跑马灯组件(marquee):展示一段单行滚动的文字。
官网链接:
在本示例中,该跑马灯组件是用于展示一段文字从左往右无限循环滚动。其中id是跑马灯组件的唯一标识。scrollamount跑马灯每次滚动时移动的最大长度,开发者可以根据实际情况给予长度。当loop=-1的时候,表示连续滚动。direction是设置跑马灯的文字滚动方向。
代码和图片示例如下:
<marquee id="customMarquee" class="customMarquee" scrollamount="{{scrollAmount}}" loop="{{loop}}" direction="{{marqueeDir}}" @bounce="onMarqueeBounce" @start="onMarqueeStart" @finish="onMarqueeFinish"> {{pageInfo.marqueeCustomData}} </marquee>
自定义弹窗容器(dialog):
dialog,自定义弹窗容器,在本例中调出省市级选择和时间选择。
官网链接:
在开发此应用中,多次用到自定义弹窗容器(dialog),开发者可以通过 this.$element('id').show();调起 dialog 弹窗,通过 this.$element('id').close();关闭 dialog 弹窗,id是dialog组件的唯一标识,定义在 dialog组件内,具体的详细页面开发者可以根据需要在dialog中进行编写代码。
代码与图片示例与下面滑动选择器(picker)合并展示。
滑动选择器(picker)
滑动选择器(picker),滑动选择器组件,类型支持普通选择器,日期选择器,时间选择器,时间日期选择器,多列文本选择器。
官网链接:
在本例中dialog自定义弹窗容器和滑动选择器(picker)两者联合使用,点击选择会弹出Dialog,页面会有时间选择器和省市级联选择器。
用户在弹出的时间选择器上选择日期,点击确定,页面上的数据也会同时改变。省市级联选择器,同理。其中日期选择器:type="date"。省市级联选择器:type="multi-text"我们选择多列文本选择器。 @columnchange是当多列文本选择器中某一列的值改变时会触发此事件,columns是设置多列文本选择器的列数。range是设置多列文本选择器的选择项。value是设置多列文本选择器的值,即页面上显示的默认值,@change当用户选择的值点击确认按钮时触发该事件
代码与图片如下(这里仅展示时间选择图片)展示如下:
<dialog id="simpledialog" class="dialog-main"> <div class="dialog-div"> <div> <div class="container-margin-left-comm"> <image src="/common/computer/computer1.png" class="dialog-div-titleimage"> </image> </div> <div class="dialog-flex-justify"> <text class="dialog-divs-text1"> {{pageInfo.annualPrice}} </text> <text class="dialog-divs-text2"> {{pageInfo.inventory}} </text> </div> <image src="/common/computer/icon-close.png" class="dialog-divs-icon-close" @click="cancelSchedule"> </image> </div> <div class="dialog-div-select"> <div> <text class="dialog-div-select-text"> {{pageInfo.selectRewardTime}} </text> <div class="dialog-div-select-picker"> <picker type="date" selected="{{ newDate }}" hours="24" value="{{ newDate }}" @change="changeDate" @cancel="cancelDate"> </picker> </div> </div> <div> <text class="dialog-div-select-text"> {{pageInfo.selectRewardCity}} </text> <div class="dialog-div-select-picker"> <picker type="multi-text" @columnchange="columnTextData" columns="3" range="{{cityList}}" value="{{selectCityList}}" @change="changeCity"> </picker> </div> </div> </div> <div class="dialog-div-bottom" @click="buy"> <text class="dialog-div-bottom-text"> {{pageInfo.nowSell}} </text> </div> </div> </dialog>
菜单(menu)
菜单(menu),提供菜单组件,作为临时性弹出窗口,用于展示用户可执行的操作。
官网链接:
在本示例中,该菜单组件展示四个菜单内容分别为:评分、分享、浏览量、退出。当用户点击任意菜单内容,都会执行对应的事件逻辑。其中 id是菜单组件的唯一标识,可以通过this.$element("id").show调起菜单组件。@selected是当选中菜单中某个值被点击选中时触发的事件
代码如下:
<menu id="apiMenu" @selected="onMenuSelected"> <option value="Item-1"> {{pageInfo.scoring}} </option> <option value="Item-2"> {{pageInfo.sharing}} </option> <option value="Item-3"> {{pageInfo.views}} </option> <option value="Item-4"> {{pageInfo.exit}} </option> </menu>
右上角操作菜单(menu),点击即会出现一系列菜单选项可供选择,如图所示:
评分条组件(rating)
评分条,相信开发者都不陌生。点击评分,会弹出带有评分弹框的dialog弹窗容器。
官网链接:
在本示例中,该评分条组件用于给软件评分,用户可以选择0-5颗星进行打分,其中可以出现0.5的情况,例如:2.5分、3.5分。numstars设置评分条的星级总数,默认为5。 rating设置评分条当前评星数,即默认评星数。 @change当评分条的评星发生改变时触发该事件。
代码及图片如下:
<rating numstars="5" rating="{{ratingNum}}" @change="ratingChange"> </rating>
进度条组件(progress):
进度条,在本Demo中,点击立即抢购会弹出一个含有进度条(progress)的弹框。
官网链接:
在本示例中,该进度条组件用于商品抢购,当点击抢购按钮,系统会弹框显示进度条组件,进度条从0-100,当进度达到100%,会提示抢购成功。type="scale-ring"设置成带刻度圆环形进度条。 percent最初页面当前进度的值。secondarypercent最初页面次级进度的值。
图片示例和代码如下:
<progress class="min-progress" type="scale-ring" percent="{{progress.percent}}" secondarypercent="{{progress.secondarypercent}}"> </progress>
ViewChart代码文件
ViewChart代码文件于构建商品数据分析页面。
商品数据分析页面
商品数据分析页面在本Demo中仅为了呈现图表及按钮组件,通过商品详情页面右上角的菜单中的“浏览量”中进入。涉及的组件包括chart组件和button组件。
图表组件(chart)
chart组件为图表组件,用于呈现线形图、柱状图、量规图界面,本例中用的曲线图可以实时动态更新数据,其中,type="line",把图表设置成线形图。 ref="linechart",
用来指定指向子元素或子组件的引用信息,该引用将注册到父组件的$refs 属性对象上,我们最常用到的就是用ref 对图标进行添加数据this.$refs.linechart.append()。 options是设置图表参数, datasets设置图标的数据集合及其背景颜色
代码及图片示例如下:
<chart class="chart-data" type="line" ref="linechart" options="{{lineOps}}" datasets="{{lineData}}"> </chart>
按钮组件(button)
按钮组件最常用到的组件,该组件包括胶囊按钮、圆形按钮、文本按钮、弧形按钮、下载按钮。这里就不赘述了。
官网链接:
在开发应用中,在开发此应用中,是和chart组件结合起来使用的,当我们触发第一个按钮的时候,我们会加快chart组件刷新数据的速率,当我们触发第二个按钮的时候,我们会手动随机添加一个数据。
代码及图片如下:
<button value="setInterval" onclick="autoAddData" class="button-sty"> </button> <button value="Add data" onclick="addData" class="button-sty"> </button>
至此,我们已经通过一个简单的购物应用,体验了JS的15个常见组件,看到这里,你是不是已经对于这些组件有了更为全面的了解,那就赶紧上手试试吧。
本文源码下载:https://gitee.com/openharmony/codelabs/tree/master/ShoppingJs
Codelab所有源码下载:https://gitee.com/openharmony/codelabs