帝心:全网首发HarmonyOS4.0教程(哔哩哔哩)创作者。致力于推广鸿蒙教程开发。
前置知识
1. 类和对象
定义书籍类。由如下属性:
- 书籍编号标识:
id - 书名:
bookName - 作者:
author - 描述:
summary - 封面图片:
coverImg - 书籍介绍视频:
video
a. 书籍类
class Book {
id: string = '000'
bookName: string = '帝心的书'
author: string = '帝心'
summary: string = '南州知我意,吹梦到西洲'
coverImg: string = '/images/defaultLibrary.png'
video: string = '/video/dxinVideo1.mp4'
constructor(id: string, bookName: string, author: string, summary: string, coverImg: string, video: string) {
this.id = id
this.bookName = bookName
this.author = author
this.summary = summary
this.coverImg = coverImg
this.video = video
}
}
以上定义方式,所有参数为必传参数。即,创建对象时,需要按照顺序逐个传入属性值。
b. 创建对象
new Book('001','红楼','雪芹','真作假时假亦真 无为有处有还无','/image/honglou.png','/video/dxinVideo1.mp4')
c. 参数省略
创建类时给定了默认属性值。如果创建对象时不想传递参数。则可以免写指定参数。
注意:
- 部分参数省略时,要放在构造函数参数列表的最后部分。
- 本示例演示全部可省参数
class Book {
id?: string = '000'
bookName?: string = '帝心的书'
author?: string = '帝心'
summary?: string = '南州知我意,吹梦到西洲'
coverImg?: string = '/images/defaultLibrary.png'
video?: string = '/video/dxinVideo1.mp4'
constructor(id?: string, bookName?: string, author?: string, summary?: string, coverImg?: string, video?: string) {
this.id = id
this.bookName = bookName
this.author = author
this.summary = summary
this.coverImg = coverImg
this.video = video
}
}
d. 创建对象
new Book()
new Book('001', '红楼', '雪芹', '真作假时假亦真 无为有处有还无', '/image/honglou.png', '/video/dxinVideo1.mp4')
new Book('001', '红楼', '雪芹', '真作假时假亦真 无为有处有还无')
e. 简写形式
如果一个类属性过多,需要在类中书写多行属性声明,且在构造函数中挨个赋值。代码臃肿。可简化书写形式。
class Book {
constructor(
public id?: string,
public bookName?: string,
public author?: string,
public summary?: string,
public coverImg?: string,
public video?: string
) { }
}
2. HTTP交互和云
a. 注册登录华为云官方网站
b. 创建华为云函数
华为云首页搜索云函数工作流参考文档进行学习使用
3. JSON文件读取和解析
JSON文件作为一种轻量级的文本格式,用于表示结构化数据。JSON 文件通常以 .json 作为文件扩展名,例如 data.json。
JSON 文件常用于以下场景:
- 配置文件: 存储应用程序或系统的配置信息。
- 数据交换: 在不同系统之间传递数据,例如 Web 服务返回的数据。
- 数据存储: 保存或导出数据,例如日志文件、用户设置、游戏数据等。
基本结构:
一个 JSON 文件通常由一个 JSON 对象或一个 JSON 数组组成。JSON 对象是一组无序的键值对,而 JSON 数组是一组有序的值。以下是 JSON 文件的两个基本结构:
JSON 允许在对象中嵌套对象,也允许在数组中嵌套数组或对象。
JSON 支持以下数据类型:
- 字符串(String): 使用双引号括起来的文本。
- 数字(Number): 整数或浮点数。
- 布尔值(Boolean):
true或false。 - 数组(Array): 有序的值的列表。
- 对象(Object): 无序的键值对集合。
- null: 表示空值。
JSON文件中不允许写注释
[
{
"id": "0",
"bookName": "南风意",
"author": "帝心",
"summary": "南风知我意,吹梦到西州",
"coverImg": "/images/dixin.jpg",
"video": "/video/dxinVideo1.mp4"
},
{
"id": "1",
"bookName": "红楼梦",
"author": "曹雪芹",
"summary": "《红楼梦》,中国古代章回体长篇小说,中国古典四大名著之一。其通行本共120回,一般认为前80回是清代作家曹雪芹所著,后40回作者为无名氏,整理者为程伟元、高鹗。小说以贾、史、王、薛四大家族的兴衰为背景,以富贵公子贾宝玉为视角,以贾宝玉与林黛玉、薛宝钗的爱情婚姻悲剧为主线,描绘了一些闺阁佳人的人生百态,展现了真正的人性美和悲剧美,是一部从各个角度展现女性美以及中国古代社会百态的史诗性著作。",
"coverImg": "/images/honglou.jpg",
"video": "/video/dxinVideo1.mp4"
},
{
"id": "2",
"bookName": "西游记",
"author": "施耐庵",
"summary": "该小说主要讲述了孙悟空出世,跟随菩提祖师学艺及大闹天宫后,遇见了唐僧、猪八戒、沙僧和白龙马,西行取经,一路上历经艰险,降妖除魔,经历了九九八十一难,终于到达西天见到如来佛祖,最终五圣成真的故事。该小说以“玄奘取经”这一历史事件为蓝本,经作者的艺术加工,深刻地描绘出明朝时期的社会生活状况。",
"coverImg": "/images/xiyou.jpg",
"video": "/video/dxinVideo2.mp4"
},
{
"id": "3",
"bookName": "三国演义",
"author": "罗贯中",
"summary": "哥们躬耕于南阳,瘪三往返三趟,问其天下事,满朝文武吱吱呜呜,吾仰天长啸:自董卓睡貂蝉以来,天下豪杰并起,跨洲连郡者不可胜数,唯吕布恨我最甚",
"coverImg": "/images/sanguo.jpg",
"video": "/video/dxinVideo1.mp4"
},
{
"id": "4",
"bookName": "水浒传",
"author": "帝心",
"summary": "唐僧路过贾府跟黛玉化缘,黛玉相中活泼悟空,遂结良缘。悟空书上偷桃,黛玉树下脏话,鲁智深看不下去,一把把树拔了起来",
"coverImg": "/images/shuihu.jpg",
"video": "/video/dxinVideo2.mp4"
},
{
"id": "5",
"bookName": "金瓶梅",
"author": "泽宇",
"summary": "泽宇哥哥与邻家官人日がたつにつれて情がわく",
"coverImg": "/images/jinpingmei.jpg",
"video": "/video/dxinVideo1.mp4"
}
]
{
"books":[
{
"id": "0",
"bookName": "南风意",
"author": "帝心",
"summary": "南风知我意,吹梦到西州",
"coverImg": "/images/dixin.jpg",
"video": "/video/dxinVideo1.mp4"
},
{
"id": "1",
"bookName": "红楼梦",
"author": "曹雪芹",
"summary": "《红楼梦》,中国古代章回体长篇小说,中国古典四大名著之一。其通行本共120回,一般认为前80回是清代作家曹雪芹所著,后40回作者为无名氏,整理者为程伟元、高鹗。小说以贾、史、王、薛四大家族的兴衰为背景,以富贵公子贾宝玉为视角,以贾宝玉与林黛玉、薛宝钗的爱情婚姻悲剧为主线,描绘了一些闺阁佳人的人生百态,展现了真正的人性美和悲剧美,是一部从各个角度展现女性美以及中国古代社会百态的史诗性著作。",
"coverImg": "/images/honglou.jpg",
"video": "/video/dxinVideo1.mp4"
},
{
"id": "2",
"bookName": "西游记",
"author": "施耐庵",
"summary": "该小说主要讲述了孙悟空出世,跟随菩提祖师学艺及大闹天宫后,遇见了唐僧、猪八戒、沙僧和白龙马,西行取经,一路上历经艰险,降妖除魔,经历了九九八十一难,终于到达西天见到如来佛祖,最终五圣成真的故事。该小说以“玄奘取经”这一历史事件为蓝本,经作者的艺术加工,深刻地描绘出明朝时期的社会生活状况。",
"coverImg": "/images/xiyou.jpg",
"video": "/video/dxinVideo2.mp4"
},
{
"id": "3",
"bookName": "三国演义",
"author": "罗贯中",
"summary": "哥们躬耕于南阳,瘪三往返三趟,问其天下事,满朝文武吱吱呜呜,吾仰天长啸:自董卓睡貂蝉以来,天下豪杰并起,跨洲连郡者不可胜数,唯吕布恨我最甚",
"coverImg": "/images/sanguo.jpg",
"video": "/video/dxinVideo1.mp4"
},
{
"id": "4",
"bookName": "水浒传",
"author": "帝心",
"summary": "唐僧路过贾府跟黛玉化缘,黛玉相中活泼悟空,遂结良缘。悟空书上偷桃,黛玉树下脏话,鲁智深看不下去,一把把树拔了起来",
"coverImg": "/images/shuihu.jpg",
"video": "/video/dxinVideo2.mp4"
},
{
"id": "5",
"bookName": "金瓶梅",
"author": "泽宇",
"summary": "泽宇哥哥与邻家官人日がたつにつれて情がわく",
"coverImg": "/images/jinpingmei.jpg",
"video": "/video/dxinVideo1.mp4"
}
]
}
a. 读取JSON文件
导入即对象
import book from 'resources/rawfile/book.json'
import book from 'resources/rawfile/book.json'
import Book from '../model/Book'
@Entry
@Component
struct ReadJSON {
build() {
Column({ space: 30 }) {
Text('读取JSON并解析数据到Book类型').fontSize(30)
List({ space: 20 }) {
ForEach(book, (bookItem: Book) => {
ListItem() {
Row() {
Image(bookItem.coverImg).width(100)
Column() {
Text(bookItem.bookName).fontSize(22)
Text(bookItem.author).fontColor('#ffd43020')
Text(bookItem.summary)
// .maxLines(2)
// .textOverflow({ overflow: TextOverflow.Ellipsis })
.textOverflow({ overflow: TextOverflow.MARQUEE })
}
.width('60%')
.height('100%')
.justifyContent(FlexAlign.SpaceAround)
}
.width('90%')
.height(150)
.justifyContent(FlexAlign.SpaceAround)
}
})
}
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.theme_color'))
}
}
应用开发-UI
1. 设计首页并跳转
业务逻辑
-
首页加载即从华为云函数工作流获取图书馆名称
-
- 需要先申请网络权限
-
点击logo图标跳转到图书馆主页
细节
- 华为云函数工作流的API应抽取到
src/main/ets/common/Constants.ets中,方便维护。 - 页面跳转前应提前准备好目标页,以方便使用其路由地址。
- 路由跳转,获取参数对象时要求结果是名确的对象类型。所以需要提前设计参数的对象模型
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
// 使用路由获取参数 要求获取的结果是一个对象类型
// Index页面传递参数 Library 传递的是一个字符串类型
// Library 页面传递参数 BookDetail 传递一个Book对象
import Book from './Book'
export default class RouterParam{
paramKey:string | Book = ''
}
import { http } from '@kit.NetworkKit';
import Constants from '../common/Constants';
import { router } from '@kit.ArkUI';
import IndexToLibraryParam from '../model/RouterParam';
@Entry
@Component
struct Index {
@State libraryName: string = '从华为云获取';
async aboutToAppear(): Promise<void> {
let data = await http.createHttp().request(Constants.getLibraryName)
this.libraryName = data.result as string
}
build() {
Column({ space: 30 }) {
Image($r('app.media.logo'))
.width(200)
.onClick(() => {
router.pushUrl({
url: "pages/Library",
params:{
paramKey:this.libraryName
}
})
})
Text(this.libraryName)
.fontSize(30)
.fontColor($r('app.color.titile_color'))
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor($r('app.color.theme_color'))
}
}
2. 图书馆主页
- 图书馆名称:从首页传递过来的参数中解析
- 图书馆描述:从华为云函数获取
> 前文创建过响应图书馆名称的函数,可以继续创建更多函数。
- 图书列表:读取
book.json文件并渲染UI
import Book from '../model/Book'
import book from 'resources/rawfile/book.json'
import router from '@ohos.router'
import RouterParam from '../model/RouterParam'
import { http } from '@kit.NetworkKit'
import Constants from '../common/Constants'
@Entry
@Component
struct Library {
//路由参数对象
paramObj: RouterParam = router.getParams() as RouterParam
// 图书馆名称
libraryName: string = this.paramObj?.paramKey as string || 'libraryName'
// 图书馆描述 来源于华为云函数
@State libraryDescription: string = '描述'
async aboutToAppear(): Promise<void> {
// 访问华为云获取 图书馆描述
let data = await http.createHttp().request(Constants.getLibraryDesc)
this.libraryDescription = data.result as string
console.log(this.libraryDescription)
}
build() {
Column({ space: 30 }) {
Text(this.libraryName)
.fontSize(30)
.fontColor($r('app.color.titile_color'))
Text(this.libraryDescription)
.fontSize(20)
.fontColor('#ff83802a')
List({ space: 20 }) {
ForEach(book, (bookItem: Book) => {
ListItem() {
Row() {
Image(bookItem.coverImg).width(100)
Column() {
Text(bookItem.bookName).fontSize(22)
Text(bookItem.author).fontColor('#ffd43020')
Text(bookItem.summary)// .maxLines(2)
// .textOverflow({ overflow: TextOverflow.Ellipsis })
.textOverflow({ overflow: TextOverflow.MARQUEE })
}
.width('60%')
.height('100%')
.justifyContent(FlexAlign.SpaceAround)
}
.width('90%')
.height(150)
.justifyContent(FlexAlign.SpaceAround)
}
.width('90%')
.borderRadius(10)
.backgroundColor('#fff1c2e0')
.onClick(() => {
// 跳转到书籍详情页
router.pushUrl({
url: "pages/BookDetail",
params: {
paramKey:bookItem
}
})
})
})
}
.width('100%')
.alignListItem(ListItemAlign.Center)
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.theme_color'))
}
}
3. 书籍详情页
- 顶部:返回按钮+当前图书名
- 主体:书籍图片+作者+书籍描述+书籍视频
// 书籍详情页
import Book from '../model/Book'
import { router } from '@kit.ArkUI'
import RouterParam from '../model/RouterParam'
@Entry
@Component
struct BookDetail {
book: Book =
(router.getParams() as RouterParam)?.paramKey as Book || new Book("000", "书名", "作者", "描述", "封面", "视频")
//视频控制器
videoController:VideoController = new VideoController()
build() {
Column({ space: 30 }) {
// 顶部返回按钮 + 图书名
Row() {
Image($r('app.media.ic_public_back'))
.width(40)
.onClick(() => {
router.back()
})
Text(this.book.bookName)
.font({
size: 40, weight: 700, style: FontStyle.Italic
})
.fontColor('#ffc627a4')
}
.width('100%')
.height(60)
.justifyContent(FlexAlign.SpaceAround)
// 书籍图片 + 作者 + 书籍描述 + 视频
Image(this.book.coverImg)
.width('30%')
List() {
ListItem() {
Column({ space: 30 }) {
Text(this.book.author)
.font({ size: 30 })
.fontColor('#ff1813b5')
Text(this.book.summary)
.font({ size: 20 })
.fontColor('#ff0b566d')
Video({ src: this.book.video, controller: this.videoController})
.width('80%')
.height('50%')
.autoPlay(false)
.controls(true)
.loop(false)
}
}
}
.width('100%')
.layoutWeight(1)
.backgroundColor('#eee')
}
.width('100%')
.height('100%')
.backgroundColor($r('app.color.theme_color'))
}
}
4. 运行效果
电话服务
电话服务仅需一行代码即可实现。自行设计UI效果,绑定点击事件。
Text(){
Span('图书馆电话')
Span('15890100305')
.fontColor('#ff0fa3e7')
.fontSize(20)
.onClick(() => {
//电话服务功能实现 :点击电话号码可以跳转到拨打电话界面
call.makeCall("15890100305")
})
}