首发!点歌系统也有鸿蒙版了?老王抢先体验了一把

大家好,我是老王~

鸿蒙前段时间新出了方舟开发框架,声明式开发模式,和react就很相似。此项目基于开发,算是一个比较完善的系统。

在做这个项目过程中遇到了很多问题,能解决的都解决了,不能解决的会在此提出,后面框架升级解决后会再次更新。

接下来将从这几个方面讲解开发的系统,项目目录、开发过程、还有最主要的组件相关内容等。

一、实现效果

二、项目目录

三、组件实现组件

其实很简单,使用@Component修饰的结构体都具有组件化能力

组件的各种修饰器

@Entry:如果你想让该组件作为你这个页面的默认入口就需要使用这个修饰器

@Preview:可以在DevEco的PC预览上进行单组件预览

@Builder:在一个自定义组件内快速生成多个布局内容,我觉得这个很鸡肋,直接使用自定义组件也是可以的

@Ext:这个组件比较实用,如果想覆盖自定义组件的一些属性,直接使用这个组件修饰即可修改

组件定义和使用

新建一个Components文件夹,文件夹中放各种组件

组件需要使用es6的import导入、export导出

//组件定义@ComponentexportstructComponent{build(){Text('我的第一个组件')}}//组件使用import{Component}from'你的文件路径'Component()
组件的数据通信

父组件传值到子组件,父组件直接传值过去即可,如:Component({value:'传递的值'}),子组件接收的话,需要定义一个value属性接收

如果更改数据后需要页面同步更改需要使用@States修饰进行修饰

父子组件双向通信,父组件需要定义value属性,并使用@States修饰器修饰,子组件定义value属性接收,同时使用@Link修饰器修饰,这样子组件数据修改后父组件会同步修改

子组件调用父组件方法,文档中并没有相关说明,但是如果想要调用父组件方法的话可以先双向通信,然后父组件中使用@Watch修饰器监听属性变化,属性一旦变化执行相应方法

四、项目开发主入口

数据改变页面不会刷新,如果想要页面进行刷新,需要给依赖的数据增加装饰器@State,同时@State修饰的数据对组件显隐有一定作用

数据超出限定范围,是无法滚动的,需要给超出组件外层包裹Scroll组件

主要代码

@Entry@ComponentstructIndex{@StatecurrentId:number=1build(){Column(){Scroll(){Column(){if(===1){//点歌页面ChooseSong()}elseif(===2){//遥控页面RemoteControl()}else{//我的页面Home()}}.width('100%')}.height('91%').scrollBarWidth(0)//底部navColumn(){MyBottomNav({currentId:$currentId})}.width('100%').height('9%')}.width('100%').height('100%')}}
点歌页面

ets框架暂时未出输入框组件,暂时采用布局写的假输入框,等出了输入框组件再行替换

弹窗事件,ets不支持,使用会报错,添加至歌曲列表的弹窗事件支持后会加入进去。

这个页面有5个组件,搜索框组件、menu组件、title组件、歌曲推荐组件、歌曲列表组件

代码

//主入口@Entry@ComponentexportstructChooseSong{@StatecurrentId:number=1@State@Watch("clickHandle")isClick:boolean=false@StatesearchValue:string=''clickHandle(){({uri:'pages/search'})}build(){Column(){//搜索框Flex({justifyContent:}){MySearch({isClick:$isClick,searchValue:$searchValue})}.margin({top:15}).width('100%')//轮播图Swiper(){ForEach(bannerImage,(item)={Image().width('100%').height('100%').border({radius:10})},item=)}.width('92%').height(150).margin({top:15}).index(1).autoPlay(true)//子menuFlex({justifyContent:}){MyMenu({menuList:songMenu})}.margin({top:15}).width('100%')//热门推荐Column(){MyTitle({title:'热门推荐'})SongSheet({dataList:songRecomm,isShowAll:true})}.margin({top:15}).width('100%')//新歌速递Column(){MyTitle({title:'新歌速递'})SongList({dataList:songData})}.margin({top:30}).width('100%')}.width('100%')}}//输入框组件@ComponentexportstructMySearch{@LinkisClick:Boolean@LinksearchValue:stringbuild(){Flex({alignItems:}){Image($r('')).width(24).height(24).margin({left:10,right:10})Text(?:'搜索歌曲、歌手').fontSize(16).fontColor(?'999')}.width('92%').height(40).backgroundColor('000')}.width().height().backgroundColor(?'000')}.width('33%').margin({top:10}).onClick(()={({uri:'pages/search',params:{searchValue:,isShowAll:}})})},item=)}.width('92%').margin({top:10})}}//歌曲列表组件@ComponentexportstructSongList{@StatedataList:song[]=[]setDataList(id){(id)=(item={===id?{item,star:!}:item})}build(){Column(){ForEach(,(item)={Flex({alignItems:}){Column(){Text().fontSize(16).fontColor('666').margin({top:3})}.width('66%').alignItems().margin({left:'5%'})Flex(){Image($r('')).width(30).height(30).margin({right:8}).onClick(()={('加入列表')})Image(?$r(''):$r('')).width(30).height(30).onClick(()={()})}.width('23%')}.width('100%').border({width:%2?1:0,color:'999')}.margin({top:15}).width('100%')Flex({justifyContent:}){ForEach(menuList,item={Column(){Flex({justifyContent:,alignItems:}){Image().width(30).height(30)}.width(60).height(60).border({radius:30}).margin({bottom:10}).linearGradient({angle:0,direction:,colors:})Text().fontSize(16)}.width('23%')},item=)}.width('100%').margin({top:50})//轮播图Swiper(){ForEach(bannerImage,(item)={Image().width('100%').height('100%').border({radius:10})},item=)}.width('92%').height(150).margin({top:100}).index(1).autoPlay(true)}.width('100%')}}//增加减少开关@ComponentexportstructMySwitch{@Linkvalue:numberbuild(){Flex(){//减少Button({type:,stateEffect:true}){Text('-').fontSize(40).fontColor('005bea').margin({left:2,top:2}).onClick(()={=1})//增加Button({type:,stateEffect:true}){Text('+').fontSize(40).fontColor('fa71cd').onClick(()={+=1})}.border({width:2,color:'eee')}}//个人信息卡片@ComponentexportstructPerInfo{build(){Column(){Column(){Image($r('')).width(80).height(80).border({radius:40,width:3,color:'fff').height(200).margin({top:-120}).border({radius:10})}}
搜索页

通过输入框是否有值来判断是否展示热门搜索

通过监听输入框的值的变化来过滤歌曲库,展示搜索过后的歌曲

代码

@Entry@ComponentstructSearchPage{@State@Watch("clickHandle")isClick:boolean=false@State@Watch("changeValue")searchValue:string=''@StateisShowAll:boolean=falsedataList:object[]=[]setDataList(){if(){=(item={()0.5?-1:1})returnfalse;}=(item={(()+()+'')return(()!==-1||()!==-1)?item:''})}changeValue(){()}aboutToAppear(){=()?().searchValue:''=()?().isShowAll:()}clickHandle(){('弹出输入键盘')}build(){Scroll(){Column(){//搜索框Flex({justifyContent:}){MySearch({isClick:$isClick,searchValue:$searchValue})}.margin({top:15}).width('100%')if(||){Column(){MyTitle({title:'搜索结果'})SongList({dataList:})}.margin({top:30}).width('100%')}else{//热门搜索Flex({direction:}){Text('热门搜索').fontSize(16).fontColor('#999')BreadBlock({searchValue:$searchValue})}.width('92%').margin({top:15})}}.width('100%')}}}//热门搜索@ComponentexportstructBreadBlock{@LinksearchValue:stringbuild(){Flex({wrap:}){ForEach(hotSearchList,item={Text(item).fontSize(16).padding({left:15,right:15,top:16}).onClick(()={=item})},item=item)}}}

方舟开发框架现在还不是很完善,开发完整大型项目还是很费力,但是一些小dome还是可以开发的。希望框架越来越完善,毕竟声明式开发是未来的开发的主流趋势。

最后附上git地址:

——————

原创:老王丨【公众号:鸿蒙开发者老王】华为认证讲师/腾讯认证讲师/鸿蒙开发先行者

发布于 2025-02-20
89
目录

    推荐阅读