前言
本文将会带着大家做一个完整的项目,但是不包含后端,如果需要后端云开发的话,后期再给大家补上
本来最开始是想带着大家做鸿蒙官方的CodeLabs
的,但是我看现在网上已经出了很多教程,尤其是机构,他们到时候应该会以视频教学的方式带着大家做,所以我就不做CodeLabs
了,决定自己做一个单出的Demo
,因为自己做的话需要设计等因素,所以拖了蛮长时间的
最后的项目代码我传到了Gitee
上供大家参考,因为我自己也懒得用Github
...
好的,我们开始吧
登陆页面
我们新建项目,选择空模板就行了,创建完是这个样子的

我现在需要添加一个登录页和注册页,就直接新建两个Page

我现在想新建一个常量的文件,用来存放一些常量,例如一些文字大小
,颜色
等等

于是新建一个common
并且新建一个Constant.ets
然后我先定义一下我登陆页面标题
的内容数据,这种数据的格式推荐是大写,然后多个单词用_
进行分割

然后在登陆页面使用

然后输入框我们用TextInput
组件来完成

我们先简单做成这种效果,然后我们把一些别的地方也会用到的公共的常量拿出来

然后我们在Login中使用

这里可能有人会说,为什么不封装一个Form组件呢?其实我最开始也是这么想的,因为登陆和注册都需要一个表单,但是在写的过程中我发现其实也并不怎么省事,而且我设想的后期的登陆和注册页面可能区别较大
当然,如果这里你想封装一个Form组件的话是完全可以的~
现在我们想获取到输入框的值,并且希望点击Button
进行页面跳转,跳转到Index


这里顺便传了个参数,其实这个用户名密码应该存在应用里的,但是这里就当是复习一下传参吧
然后Index接收

现在的效果是这样的

然后我们同样的逻辑,搞一下注册页面
注册页面

我们先在这里加一行,可以跳转到注册
然后页面和Login
一个逻辑
ts
import router from '@ohos.router'
import Constant from '../common/Constant'
@Entry
@Component
struct Register {
@State message: string = 'Please Register'
@State username: string = ''
@State password: string = ''
@State email: string = ''
build() {
Row() {
Column() {
Text(this.message)
.fontColor(Constant.LOGIN_COLOR)
.fontSize(Constant.LOGIN_SIZE)
.fontWeight(FontWeight.Bold)
TextInput({ placeholder: 'Username' })
.margin({ top: 20 })
.width(Constant.INPUT_WIDTH)
.height(Constant.INPUT_HEIGHT)
.onChange((value: string) => {
this.username = value
})
TextInput({ placeholder: 'Email' })
.margin({ top: 20 })
.width(Constant.INPUT_WIDTH)
.height(Constant.INPUT_HEIGHT)
.onChange((value: string) => {
this.email = value
})
TextInput({ placeholder: 'Password' })
.type(InputType.Password)
.margin({ top: 20 })
.width(Constant.INPUT_WIDTH)
.height(Constant.INPUT_HEIGHT)
.onChange((value: string) => {
this.password = value
})
Button('Register')
.width(Constant.BUTTON_WIDTH)
.height(Constant.BUTTON_HEIGHT)
.margin({ top: 30 })
.backgroundColor(Constant.BUTTON_COLOR)
.onClick(() => {
router.pushUrl({
url: 'pages/Login',
params: {
username: this.username,
password: this.password,
email: this.email
}
})
})
}
.width('100%')
}
.height('100%')
}
}

这是最后效果,最终调到Login
页面
目前较为简洁哈,后面会改善一下
Index
我们首先先通过Tabs
将底部导航栏搞出来

现在代码太乱了,我们希望Index干净一些,所以需要封装一下
我们先将Tabs
的内容封装成一个组件,叫做TabBar
ets
下新建一个views
文件夹用来存放组件,然后新建一个TabBar.ets

然后把Tabs
下的内容都放在TabBar
组件下,并导出

然后在Index
中引入并使用

效果是一样的
然后我们关注每个TabContent
即可
首页Home
先从我们的首页开始
我们把首页的内容也做成一个组件,叫做Home
然后在TabBar引入并使用

OK,好的,我们开始专心开发Home
的内容吧
Search搜索框
首先在顶部,我想有一个搜索框

现在搜索框完事了,但是代码也有点冗余了,所以我把这部分也抽出去,万一以后别的地方会用呢


这里的@Preview
是我为了能够单独预览组件用的
OK,效果是一样的,我们继续往下了
这里注意,你完全可以去用自带的Search
组件

但是对我来说,其实写的没差太多,而且我想更自由化一点,具体选择看你的场景即可
我先加上一个标题

List
然后下面是一个列表,那我就要去用List
组件了

List
是一个容器组件,它里面的内容需要用ListItem
进行填充,同时又需要多个ListItem,这就用到了之前学过的列表的循环渲染ForEach
现在的效果是这样的

同时拉到最底部的时候会触发onReachEnd
事件,可以用来做一些操作
显然,我们这个List不能直接放在这里,于是封装一个ProductList
组件

在Home
中引用

效果是一样的
刷新Refresh
然后正常的列表应该是可以下拉刷新
的,下拉刷新我们有两种方式
- 封装一个刷新组件
- 用ArcUI的组件
这里我们就用Arc提供给我们的组件了,之后我看看优化的时候可以考虑封装一个
其实在官网的CodeLabs中就有一个封装的刷新组件了,大家可以看看
链接给大家自定义下拉刷新动画(ArkTS) (huawei.com)
好的,那我们这里用自带的刷新组件Refresh

这是效果

ListItem
好的,现在我们专注于ListItem
的内容

我们先看看效果,显然,里面有很多数据,这时候我们就需要去写数据了
我们在ets
下新建一个viewModel
文件夹,用来存放数据
然后我们新建一个ProductData.ets
用来放商品数据

这里的Resource
是指去拿资源里的数据,这里我拿的是图片,其实一些数据名或者是颜色在element
里面都可以进行设置

这里大家知道就好,并不是什么难的东西,目前我先不放在这里

然后我进行使用,并设计一下每个ListItem

目前的效果是这样的
这里的过期提示我设置的是一个Button
,因为我打算后期加一些功能
然后过期、新鲜
两种状态我设置了不同的颜色,我现在想要做一个判断,用来让按钮显示不同的颜色,那么就需要用条件渲染
了

这样就可以进行动态的判断了
我的页面
现在我们来做Mine
模块

OK,我们新建了一个Mine.ets
并且在TabBar
里面进行引用,现在我们专注于Mine
模块即可

我现在想要这种类型的输入框,但是Arc原生并没有提供,所以需要我们封装一下

然后我们通过传参
的形式在Mine
给TextPro
赋值


OK,效果出来了
然后我们再加上一行个性签名

现在我们需要功能更加复杂的输入框

然后可以点击弹出弹出框

OK,我们来搞一下
我们这回封装一个TextPlus
组件

大部分和之前的都一样,不过是多了一个箭头
,然后多出了一个事件
,这个事件将会用来触发弹窗
然后我们来做弹窗部分
这里我们需求和官方的文本滑动选择器弹窗
大体是一致的,于是我们就采用这种方案

然后我们写一下



现在的效果就是这样了
结尾
目前先写到Mine模块,因为愉快的周末要结束了。。
Mine模块其实也有一部分没有完成,所以需要下一篇和大家再见啦
因为目前的项目是临时赶出来供大家学习的,有很多地方还有设计问题,希望大家提出来,然后我慢慢改,也有很多地方没抽完,比如很多常量我还没抽出来,但是大家能有这种思想就行, 我会在业余时间优化一下,然后就不单独发文了
还有几个模块没完成,预计一共3-4篇左右,其实写项目是很快的,但是一边写项目一边写文章就会很慢,希望大家谅解,尽量!一周內更完!
然后我在考虑是否出云开发的模块,因为我是云开发的忠实粉丝(uni全栈全家桶的忠实爱好者),需要的话可以评论或者私信
同时大家有什么问题都可以评论或者私信问我,因为其实还蛮多坑的
同时,关于鸿蒙的低代码
开发,我也体验了一下,比较方便,比如一些简单的页面用低代码的形式也是挺快的,在最后我会带着大家用鸿蒙低代码开发一个组件~
项目地址放在这里,和教程是同步的Remind: 鸿蒙HarmonyOS的第一个demo (gitee.com),可以直接提issue
设计稿的话等我全部完成、改善完毕的时候再发给大家
期待你的关注和点赞~