【HarmonyOS】鸿蒙系统在租房项目中的项目实战(二)

        从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是什么?鸿蒙仅仅是一个手机操作系统吗?它的出现能够和Android和IOS三分天下吗?它未来的潜力能否制霸整个手机市场呢?

今天实现一个简单的小案例,从零开始讲解如何通过鸿蒙开发实现一个租房平台的案例。

目录

房源推荐搭建

封装滚动组件

状态功能适配

想看模块搭建


房源推荐搭建

接下来我们开始编写房源推荐的相关内容,首先我们先把接口写好,这里我们先根据后端返回的接口类型的数据将接口类型编写一遍:

// 公共类型
interface BaseResponse {code: number;message: string;
}
interface BaseID { id: number }
interface BaseName { name: string }
interface BaseTitle { title: string }
interface BaseSubTitle { sub_title: string }
interface BaseImageURL { imageURL: string }// 房源推荐数据
interface BaseRecommendData extends BaseResponse {data: RecommendData[]
}
interface RecommendData extends BaseID {housePicture: stringtags: BaseName[]houseTitle: stringaddress: stringrentPriceUnit: stringrentPriceListing: stringrentArea: string
}export {BaseRecommendData,RecommendData
}

然后我们根据后端的路径开始编写接口函数,将上面的类型赋值的接口的返回值当中:

import http from "../../utils/http"
import type { HomeData, BaseRecommendData } from './type'// 统一管理接口
enum API {HOME_INFO = '/home/info',ROOM_RECOMMEND = '/house/nearbyHouses'
}// 获取首页数据
export const reqHomeData = () =>http.get<any, HomeData>(API.HOME_INFO)// 获取房源推荐数据
export const reqRecommendData = () =>http.get<any, BaseRecommendData>(API.ROOM_RECOMMEND)

因为房源组件的数据仅仅是该组件要使用而已,所以我们的接口数据就只需要在该组件进行调用即可,代码如下所示:

@State roomRecommentList: RecommendData[] = []
// 获取房源数据
getRoomRecommendData = async () => {const res: BaseRecommendData = await reqRecommendData()this.roomRecommentList = res.data
}aboutToAppear(): void {this.getRoomRecommendData()
}

后面就是借助Grid布局调整调整样式即可,最终呈现的效果如下所示:

封装滚动组件

接下来我们开始封装滚动组件,因为搜索栏的组件可能多个页面都会用到,并且会随着页面的滚动的时候出现在顶部并渐变显示,这里我们也是需要对其颜色样式进行一个动态的渲染,这里我们都将其放置在公共组件当中去,这里也是用到了插槽的内容,具体如下:

如下代码我们封装了一个插槽,一个是用于放置滚动的主体内容,另一个是放置搜索栏:

interface IColor {bgColor: stringfontColor: string
}@Component
export default struct ScrollContainer {@Builder customBuilder() {}@BuilderParam navBuilderParam: ($$: IColor) => void = this.customBuilder@BuilderParam contentBuilderParam: () => void = this.customBuilder@State scrollY: number = 0 // 存储滚动条位置(y轴滚动距离)@State bgColor: string = 'rgba(0, 0, 0, 0)' // 背景颜色@State fontColor: string = 'rgba(255, 255, 255, 1)' // 字体颜色// 处理滚动事件handleScroll = (xOffset: number, yOffset: number) => {this.scrollY += yOffset // 存储滚动条位置(y轴滚动距离)this.calcColor() // 监听文字颜色变化范围}// 监听文字颜色变化范围calcColor = () => {if (this.scrollY < 10) {// 到达顶部,渐变开始this.bgColor = 'rgba(255, 255, 255, 0)'this.fontColor = 'rgba(255, 255, 255, 1)'} else if (this.scrollY <= 100) {// 渐变中(透明度 0 -> 1)const  colorOpacity = (this.scrollY - 10) / (100 - 10)this.bgColor = `rgba(255, 255, 255, ${colorOpacity})`this.fontColor = `rgba(0, 0, 0, ${colorOpacity})`} else {// 渐变结束this.bgColor = 'rgba(255, 255, 255, 1)'this.fontColor = 'rgba(0, 0, 0, 1)'}}build() {Stack() {Scroll() {Column() {this.contentBuilderParam()}.width('100%')}.width('100%').height('100%').scrollBar(BarState.Off).align(Alignment.TopStart).onDidScroll(this.handleScroll)// 搜索栏组件, 按引用传递this.navBuilderParam({ bgColor: this.bgColor, fontColor: this.fontColor })}.width('100%').alignContent(Alignment.TopStart)}
}

接下来我们需要对首页的内容进行改造一下,将原本的代码直接删掉,采用插槽的方式进行书写,因为使用@Builder会导致this指向的问题,所以我们在调用的时候,包一层箭头函数即可:

import { reqHomeData } from '../api/home'
import type { HomeData, bannerList, navList, tileList, planList } from '../api/home/type'
import { PADDING, SHADOW_RADIUS } from '../contants/size'
import SwiperLayout from '../components/Home/SwiperLayout'
import SearchBar from '../components/Home/SearchBar'
import NavList from '../components/Home/NavList'
import TitleList from  '../components/Home/TitleList'
import PlanList from '../components/Home/PlanList'
import RoomRecommend from '../components/Home/RoomRecommend'
import ScrollContainer from '../components/Container/ScrollContainer'interface IColor {bgColor: stringfontColor: string
}@Component
export default struct Home {@State bannerList: bannerList[] = []@State navList: navList[] = []@State titleList: tileList[] = []@State planList: planList[] = []@State adPicture: string = ''// 获取首页数据getHomeData = async () => {const res: HomeData = await reqHomeData()this.bannerList = res.data.bannerListthis.navList = res.data.navListthis.titleList = res.data.tileListthis.planList = res.data.planListthis.adPicture = res.data.adPicture}// 初始化页面调用aboutToAppear(): void {this.getHomeData()}@BuildernavBuilder($$: IColor) {// 搜索栏组件SearchBar({ bgColor: $$.bgColor, fontColor: $$.fontColor })}@BuildercontentBuilder() {SwiperLayout({ bannerList: this.bannerList }) // 轮播图组件使用props通信Column() {NavList({ navList: this.navList }) // 导航栏组件使用props通信TitleList({ titleList: this.titleList }) // 标题栏组件使用props通信PlanList({ planList: this.planList }) // 列表组件Image(this.adPicture) // 广告图.width('100%').height(60).objectFit(ImageFit.Fill).margin({ top: 10 }).shadow({ offsetX: 0, offsetY: 0, radius: SHADOW_RADIUS, color: 'rgba(0, 0, 0, 0.14)' })}.width('100%').padding({ left: PADDING, right: PADDING })RoomRecommend() // 推荐房源组件}build() {ScrollContainer({navBuilderParam: this.navBuilder,contentBuilderParam: () => {// 使用Builder函数,需要使用箭头函数指向this实例this.contentBuilder()},})}
}

最终呈现的效果如下所示,依然实现了原本的效果:

状态功能适配

        因为我们上面都是按照UI设计稿来设置的宽高度,也就是说我们把样式给写死了,当用户用其他不同的比例的显示器去查看我们设计的页面的时候,就会出现适配问题,为此我们需要对一些功能的状态适配问题进行相应的处理。

我们来到进入应用窗口的函数当中进行编写,将获取到的相关状态高度颜色等进行持久化存储:

然后我们可以在滚动容器当中拿到对应的对象:

windowStyle?: window.WindowgetWindowStyle = async  () => {this.windowStyle = await window.getLastWindow(getContext(this))
}

在设定颜色的内容处根据滚动距离设置不同的颜色内容:

然后我们可以根据适配器的内容设置一下适配函数,在所有的定义宽高距离的内容当中调用一下该函数进行适配:

/** 计算元素真正的大小:元素在设计稿的大小 / 设计稿总宽度 = x / 真机宽度(保证元素在不同设备占比相同)x = 元素在设计稿的大小 / 设计稿总宽度 * 真机宽度* */const DRAFT_WIDTH = 360
// 预览器获取不到宽度,给预览器默认值360
const windowWidth = AppStorage.get('windowWidth') as number || 360
const rvp = (val: number) => {return val / DRAFT_WIDTH * windowWidth
}export default rvp

然后我们给设置的每一个距离的内容都调用该函数即可:

想看模块搭建

接下来我们开始搭建想看的模块内容,首先我们先处理一下导航栏的样式内容,如下所示:

import { PADDING } from "../../contants/size"
import rvp from "../../utils/responsive"@Component
export default struct NavBar {@StorageProp('topHeight') topHeight: number = 0build() {Row() {Row({ space: rvp(6) }) {Image($r('app.media.bag')).width(rvp(16)).height(rvp(16))Text('请写通勤地址').fontSize(rvp(12)).fontColor($r('app.color.black'))}Row({ space: rvp(28) }) {Column({ space: rvp(1) }) {Image($r('app.media.message')).width(rvp(20)).height(rvp(20)).fillColor($r('app.color.black'))Text('消息').fontSize(rvp(10)).fontColor($r('app.color.black'))}Column({ space: rvp(1) }) {Image($r('app.media.journey')).width(rvp(20)).height(rvp(20))Text('行程').fontSize(rvp(10)).fontColor($r('app.color.black'))}}}.width('100%').height(rvp(44)).justifyContent(FlexAlign.SpaceBetween).padding({ left: rvp(PADDING), right: rvp(PADDING) }).margin({ top: this.topHeight })}
}

接着处理一下找房的一些图片文字资源的显示:

import { PADDING } from "../../contants/size"
import rvp from "../../utils/responsive"@Component
export default struct NavBar {@StorageProp('topHeight') topHeight: number = 0build() {Column() {Image($r('app.media.find_room')).width(rvp(60)).height(rvp(23)).margin({ left: rvp(4) })Text('发现你想看的房子').margin({ left: rvp(4), top: rvp(20) }).fontSize(rvp(12)).fontColor($r('app.color.black'))Image($r('app.media.blank')).width(rvp(234)).height(rvp(221)).alignSelf(ItemAlign.Center).margin({ top: rvp(7) })Text("暂无想看房源,试试如下找房方式").width('100%').textAlign(TextAlign.Center).margin({ top: rvp(10) }).fontSize(rvp(16)).fontColor($r('app.color.black')).fontWeight(600)Row({ space: rvp(10) }) {Row({ space: rvp(5) }) {Image($r('app.media.bus')).width(rvp(40)).height(rvp(40))Column({ space: rvp(3) }) {Text('通勤找房').fontSize(rvp(16)).fontColor($r('app.color.black'))Text('找公交车站附件房源').fontSize(rvp(12)).fontColor($r('app.color.gray'))}.alignItems(HorizontalAlign.Start)}Row({ space: rvp(5) }) {Image($r('app.media.map')).width(rvp(40)).height(rvp(40))Column({ space: rvp(3) }) {Text('地图找房').fontSize(rvp(16)).fontColor($r('app.color.black'))Text('找地图附件房源').fontSize(rvp(12)).fontColor($r('app.color.gray'))}.alignItems(HorizontalAlign.Start)}}.width('100%').height(rvp(70)).border({ width: 1, color: $r('app.color.shadow') }).margin({ top: rvp(10) }).justifyContent(FlexAlign.SpaceAround)}.width('100%').alignItems(HorizontalAlign.Start).padding({ top: rvp(54), left: rvp(PADDING), right: rvp(PADDING) })}
}

然后我们将两个封装的组件在See的想看模块中进行调用,如下所示:

import NavBar from '../components/See/NavBar'
import FindRoom from '../components/See/FindRoom'@Component
export default struct See {build() {Column() {NavBar()FindRoom()}.width('100%').height('100%').linearGradient({direction: GradientDirection.Bottom,colors: [['#DEFBE5', 0], ['#FFFFFF', 0.3]]})}
}

最终呈现的效果如下所示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/886494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Scala-字符串(拼接、printf格式化输出等)-用法详解

Scala 一、 使用 号连接字符串 在 Scala 中&#xff0c; 运算符实际上会调用 String 类的 concat 方法或者使用字符串的加法操作&#xff0c;生成一个新的字符串。 字符串是不可变的&#xff0c;每次拼接都会创建一个新的字符串。 Mr. yuTips&#xff1a; 性能相对较差&…

ISCTF2024

ezlogin 源码审计 先审源码,纯js题 const express require(express); const app express(); const bodyParser require(body-parser); var cookieParser require(cookie-parser); var serialize require(node-serialize); app.use(bodyParser.urlencoded({ e…

使用真实 Elasticsearch 进行更快的集成测试

作者&#xff1a;来自 Elastic Piotr Przybyl 了解如何使用各种数据初始化和性能改进技术加快 Elasticsearch 的自动化集成测试速度。 在本系列的第 1 部分中&#xff0c;我们探讨了如何编写集成测试&#xff0c;让我们能够在真实的 Elasticsearch 环境中测试软件&#xff0c;并…

MySQL:联合查询(2)

首先写一个三个表的联合查询 查询所有同学的每门课成绩&#xff0c;及同学的个人信息 1.我们首先要确定使用哪些表 学生表&#xff0c;课程表&#xff0c;成绩表 2.取笛卡尔积 select * from score,student,course; 3. 确定表与表之间的联合条件 select * from score,stud…

Vue3学习笔记(下)

文章目录 Vue3学习笔记&#xff08;下&#xff09;组合式API下的父子通信父传子子传父 模板引用defineExpose()provide和injectvue3新特性 - defineOptionsvue3新特性 - defineModelPiniaPinia异步写法 Vue3学习笔记&#xff08;下&#xff09; 组合式API下的父子通信 父传子…

CNN神经网络

CNN 一 基本概述二 基础知识三 经典案例 今天和大家聊聊人工智能中的神经网络模型相关内容。神经网络内容庞大,篇幅有限本文主要讲述其中的CNN神经网络模型和一些基本的神经网络概念。 一 基本概述 深度学习(Deep Learning)特指基于深层神经网络模型和方法的机器学习。它是在…

MySQL —— MySQL基础概念与常用功能介绍

文章目录 基本概念数据类型数据类型分类 约束主键约束&#xff08;PRIMARY KEY&#xff09;外键约束&#xff08;FOREIGN KEY&#xff09;使用非空约束&#xff08;not null&#xff09;使用唯一性约束&#xff08;UNIQUE&#xff09;使用默认约束&#xff08;DEFAULT&#xff…

如何在react中使用react-monaco-editor渲染出一个编辑器

一、效果展示 二、基于vite配置 1.首先安装react-monaco-editor和monaco-editor包 npm add react-monaco-editor npm i monaco-editor 2.其次创建一个单独的文件&#xff08;此处是tsx、直接用app或者jsx也行&#xff09; import { useState, useEffect } from react impo…

MySQL面试之底层架构与库表设计

华子目录 mysql的底层架构客户端连接服务端连接的本质&#xff0c;连接用完会立马丢弃吗解析器和优化器的作用sql执行前会发生什么客户端的连接池和服务端的连接池数据库的三范式 mysql的底层架构 客户端连接服务端 连接的本质&#xff0c;连接用完会立马丢弃吗 解析器和优化器…

【开源免费】基于Vue和SpringBoot的私人健身与教练预约管理系统(附论文)

本文项目编号 T 618 &#xff0c;文末自助获取源码 \color{red}{T618&#xff0c;文末自助获取源码} T618&#xff0c;文末自助获取源码 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息…

JVM--内存结构

目录 1. PC Register&#xff08;程序计数器&#xff09; 1.1 定义 1.2 工作原理 1.3 特点 1.4 应用 2.虚拟机栈 2.1定义与特性 2.2内存模型 2.3工作原理 2.4异常处理 2.5应用场景 2.6 Slot 复用 2.7 动态链接详解 1. 栈帧与动态链接 动态链接的作用&#xff1a…

手机直连卫星NTN通信初步研究

目录 1、手机直连卫星之序幕 2、卫星NTN及其网络架构 2.1 NTN 2.2 NTN网络架构 3、NTN的3GPP标准化进程 3.1 NTN需要适应的特性 3.2 NTN频段 3.3 NTN的3GPP标准化进程概况 3.4 NTN的3GPP标准化进程的详情 3.4.1 NR-NTN 3.4.1.1 NTN 的无线相关 SI/WI 3.4.1.2…

【SpringBoot】什么是Maven,以及如何配置国内源实现自动获取jar包

前言 &#x1f31f;&#x1f31f;本期讲解关于Maven的了解和如何进行国内源的配置~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f3…

阿里斑马智行 2025届秋招 NLP算法工程师

文章目录 个人情况一面/技术面 1h二面/技术面 1h三面/HR面 20min 个人情况 先说一下个人情况&#xff1a; 学校情况&#xff1a;211本中9硕&#xff0c;本硕学校都一般&#xff0c;本硕都是计算机科班&#xff0c;但研究方向并不是NLP&#xff0c;而是图表示学习论文情况&…

富士施乐DocuContre S2520报打开盖子A,取出纸张。代码077-900故障检修

故障描述: 一台富士施乐DocuContre S2520复印机开机报错:打开盖子A,取出纸张。代码077-900故障,用户之前经常卡纸,卡着、卡着就一直提示打开盖子A,取出纸张了;复印机屏幕提示如下图: 故障检修: 富士施乐DocuContre S2520复印机报打开盖子A,取出纸张。077-900的错误代…

【Ubuntu24.04】VirtualBox安装ubuntu-live-server24.04

目录 0 背景1 下载镜像2 安装虚拟机3 安装UbuntuServer24.044 配置基本环境5 总结0 背景 有了远程连接工具之后,似乎作为服务器的Ubuntu24.04桌面版有点备受冷落了,桌面版的Ubuntu24.04的优势是图形化桌面,是作为一个日常工作的系统来用的,就像Windows,如果要作为服务器来…

01.防火墙概述

防火墙概述 防火墙概述1. 防火墙的分类2. Linux 防火墙的基本认识3. netfilter 中五个勾子函数和报文流向 防火墙概述 防火墙&#xff08; FireWall &#xff09;&#xff1a;隔离功能&#xff0c;工作在网络或主机边缘&#xff0c;对进出网络或主机的数据包基于一定的 规则检…

STM32设计井下瓦斯检测联网WIFI加Zigbee多路节点协调器传输

目录 目录 前言 一、本设计主要实现哪些很“开门”功能&#xff1f; 二、电路设计原理图 1.电路图采用Altium Designer进行设计&#xff1a; 2.实物展示图片 三、程序源代码设计 四、获取资料内容 前言 本系统基于STM32微控制器和Zigbee无线通信技术&#xff0c;设计了…

Vue 中的透传,插槽,依赖注入

1. 透传attributes 在组件上使用透传attribute&#xff1a; 当你在父组件中使用子组件时&#xff0c;你可以添加一些attribute到子组件上&#xff0c;即使这些attribute没有在子组件的props中声明。 父组件&#xff1a; <!-- 父组件&#xff0c;例如 ParentComponent.vue…

Figma汉化:提升设计效率,降低沟通成本

在UI设计领域&#xff0c;Figma因其强大的功能而广受欢迎&#xff0c;但全英文界面对于国内设计师来说是一个不小的挑战。幸运的是&#xff0c;通过Figma汉化插件&#xff0c;我们可以克服语言障碍。以下是两种获取和安装Figma汉化插件的方法&#xff0c;旨在帮助国内的UI设计师…