HarmonyOS鸿蒙Next中用十分钟写一个下午茶小投票应用
HarmonyOS鸿蒙Next中用十分钟写一个下午茶小投票应用
每天都在思考今天要吃什么下午茶,不妨看看大家的选择
每天下午困倦的时候,总想点个下午茶慰劳一下忙碌的自己。设计这款app的初衷,就是一个休闲的小投票,汇集大家的选择看看什么是最受欢迎的下午茶。
选择端云一体化开发的理由
在传统开发流程中,分为前端和后端两个部分,前端负责页面展示,后端负责数据处理和逻辑。通常情况下,前端工程师只负责把数据发送给后端,并渲染显示出后端返回的数据。这样的开发逻辑导致前后端开发工程师的技术栈通常不会重叠,而端云一体化开发,似乎给前端工程师带来了更多的机会,让他们可以同时负责页面展示和数据处理。
伟大的道路从创建一个项目开始
创建APPID
登录AGC后台,填写应用名称和包名,然后点击创建
生成证书
由于端云一体化开发不支持自动签名,所以我们需要获取调试证书,在AGC后台上传csr文件生成profile和调试证书,csr证书可以参考官方文档生成
把profile和证书都下载下来
在AGC后台切换到开发与服务选项卡,打开云函数和云数据库功能
新建项目
先创建端云一体项目
注意包名需要和AGC后台保持一致,不然创建项目的时候会提示找不到
云数据库Object配置
在CloudProgram里面找到云数据库,创建一个Object,命名为VoteRecord,并且配置数据列,我这里配置了id、voteId,其中id是自增的,voteId是用户的投票,然后配置索引,我这里配置了一个VoteId索引,权限方面默认就可以了
右键点击VoteRecord,点一下生成DataEntry,这里插入一些预置数据
因为id是自增长的,所以这里直接填voteId就可以了
右键点击VoteRecord,点一下生成Server模型,方便云函数调用云数据库
创建云函数
在CloudProgram里面找到云函数,创建一个云函数,命名为submit-vote,打开函数文件夹下面的package.json,添加云函数调用云数据库的依赖 "@hw-agconnect/cloud-server": "^1.0.2"
,然后 Sync
一下,不然后续会找不到函数依赖。
添加云函数代码
获取前端传来的VoteId,然后插入到数据库中,最后统计一下数据库中不同的VoteId的数量,返回给前端
import { cloud } from '@hw-agconnect/cloud-server'
import { VoteRecord } from './VoteRecord'
let myHandler = async function(event, context, callback, logger) {
logger.info(event);
let body = JSON.parse(event.body || "{}")
let userVoteId = parseInt(body.voteId || "999") //获取投票ID
let collection = cloud.database({ zoneName: 'default' }).collection(VoteRecord)
//校验一下voteId范围在1-4之间
if (userVoteId >= 1 && userVoteId <= 4) {
//添加一条记录
const upsertNum = await collection.upsert({ voteId: userVoteId })
console.log("upsertNum:" + upsertNum)
}
//把人数统计定义出来,分别代表选ABCD的不同人
let peopleCount = [0, 0, 0, 0]
for (let i = 0; i < 4; i++) {
const result = await collection.query().equalTo("voteId", i + 1).countQuery("id")
//这里官方函数库有点问题,result提示是一个number,但实际上是一个string,必须用ignore指令跳过eslint功能
//@ts-ignore
peopleCount[i] = parseInt(result)
}
callback(peopleCount)
}
export { myHandler }
部署数据库和云函数,分别在数据库、数据、函数三个地方点击右键进行部署
部署成功后,可以使用官方工具测试函数的返回值
打开DevEco Studio的测试工具
点击测试云函数,可以看到返回一个数字数组代表测试成功
端侧开发
组件界面搭建
这里先做一个简单描述,两组展示选项分别用Column包裹后使用ForEach进行元素循环渲染,在选择框的左侧使用Radio进行单选,右侧使用Text进行文本展示,在结果框架中使用两个Span组成标签,一个显示文本,一个显示投票人数的百分比
Column() {
Column({ space: 10 }) {
ForEach(this.foodList, (food: string, index: number) => {
Row() {
// 单选框
Radio({ value: `${index + 1}`, group: 'radioGroup' })
.checked(index == 0).onChange((isChecked: boolean) => {
// 选择回调
})
// 文本标签
Text(food).margin({ left: 10 })
}
})
}
.alignItems(HorizontalAlign.Center)
.width("100%")
.margin({ top: 50 })
Button("提交").onClick(async () => {
// 提交功能
}).margin({ top: 20 })
Text("大家这样选:").margin({ top: 20 })
Column({ space: 15 }) {
ForEach(this.foodList, (food: string, index: number) => {
Row() {
Text() {
// 文本标签
Span(food)
// 百分比标签,这里考虑到分母为0的情况,需要进行判断
Span(` ${this.chosenList[index]} (${(this.chosenList.reduce((v, c) => v + c, 0) == 0 ? 0 :
Math.round(this.chosenList[index] * 100 / this.chosenList.reduce((v, c) => v + c, 0)))}%)`)
}
}
})
}
.alignItems(HorizontalAlign.Center)
.width("100%")
.margin({ top: 20 })
}.justifyContent(FlexAlign.SpaceAround)
.alignItems(HorizontalAlign.Center)
数据流开发
本案例只有一个状态变量chosenList,用于存储每个选项的选择人数,同时创建一个包裹函数用于调用云函数,传入参数选择项index,返回一个数组,数组的每个元素代表一个选项的选择人数
其余变量保存用户选择的选项index,用于在选择框的左侧进行单选,然后还有一个文本标签用于渲染选项名称
checkedItem = -1
foodList: string[] = ["咖啡", "奶茶", "汽水", "雪糕"]
@State chosenList: number[] = [0, 0, 0, 0]
async callCloudFunction(index?: number): Promise<number[]> {
let result = await cloudFunction.call({
name: 'submit-vote',
timeout: 10 * 1000,
data: {
voteId: index
}
})
console.log("result:" + JSON.stringify(result.result))
return result.result as number[]
}
页面进入时调用
函数调用方式很简单,把数据流串在一起就可以了,这里需要注意的是,因为是异步调用,所以需要使用await关键字等待函数返回结果,然后再把结果赋值给数据流。这里展示的是onDidBuild
生命周期函数,在页面构建完成后调用,这样可以刚进入页面的时候就展示数据
async onDidBuild(): Promise<void> {
this.chosenList = await this.callCloudFunction()
}
单选按钮调用
单选按钮逻辑很简单,把用户选择的index赋值给checkedItem
this.checkedItem = index + 1
按钮调用
按钮和onDidBuild类似,只是这里要把用户选择的index传进去,然后刷新投票数量,更新到结果里面
Button("提交").onClick(async () => {
this.chosenList = await this.callCloudFunction(this.checkedItem)
}).margin({ top: 20 })
证书配置和真机调试
这时候我们就可以插上我们的真机进行调试,因为模拟器不支持端云一体,所以我们需要手动配置签名并安装到真机上,配置好后插上真机,点击三角符号运行就可以了
总结
通过这个案例,我们可以看到,端云一体化开发可以让前端工程师同时负责页面展示和数据处理,这样可以提高开发效率,减少开发成本。同时,端云一体化开发也可以让前端工程师更加了解后端的开发流程,这样可以更好地进行开发。
但同时也发现了一些官方手册的问题,比如云函数的返回值类型提示是一个number,但实际上是一个string,这会导致一些问题,比如在使用官方工具测试函数的时候,和实际客户端发送的数据结构压根不一样,而官方文档完全没有提及这个事情,甚至连一个可以跑的范例都没提供。
总体来说,瑕不掩瑜,端云一体化开发确实为开发者节省了不少部署服务器和学习的时间,祝大家都能够掌握这门技术,开发出令人激动的作品。
更多关于HarmonyOS鸿蒙Next中用十分钟写一个下午茶小投票应用的实战教程也可以访问 https://www.itying.com/category-93-b0.html
所以云函数是可以访问云数据库的是吧?
更多关于HarmonyOS鸿蒙Next中用十分钟写一个下午茶小投票应用的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
这是一个很好的HarmonyOS Next端云一体化开发示例!我来补充几点技术要点:
-
云数据库配置很规范,特别是索引和权限设置合理。voteId索引能有效提升查询性能,权限配置也考虑了不同用户角色的操作需求。
-
云函数处理逻辑完整:
- 参数校验确保voteId在有效范围
- 使用upsert避免重复插入
- 统计查询使用countQuery优化性能
- 前端实现简洁高效:
- 使用@State管理状态
- 合理使用ForEach渲染列表
- 异步调用处理得当
- 需要注意的细节:
- 云函数返回类型问题确实存在,需要类型断言
- 百分比计算处理了除零情况
- 真机调试是必须的
这个示例完整展示了从云数据库配置到前端交互的全流程,对学习端云一体化开发很有参考价值。特别是将云函数和前端状态管理结合的部分,体现了HarmonyOS Next的开发特点。