一、@BuilderParam装饰器
当开发者创建了自定义组件,并想对该组件添加特定功能时,例如在自定义组件中添加一个点击跳转操作。若直接在组件内嵌入事件方法,将会导致所有引入该自定义组件的地方均增加了该功能。为解决此问题,ArkUI引入了@BuilderParam装饰器,@BuilderParam用来装饰指@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。该装饰器用于声明任意UI描述的一个元素,类似slot占位符。
@Entry
@Component
struct Page_builderParam {@State message: string = 'Hello World'title: string = ''@State isShow: boolean = true;@Builderleft() {Row() {Button("大房子").onClick(()=>{this.isShow=!this.isShowconsole.log(this.isShow+"ddd")})}}@Builderright() {Row() {Button("好车子")}}@Builderlist1(){Column(){ForEach(["住宅","写字楼","商铺"],item=>{Text(item).fontColor(Color.Green).fontSize(19)})}}build() {Row() {Column() {Nav({ title: "金山", left: this.left.bind(this), right: this.right })if(this.isShow){list({list1:this.list1})}}.width('100%')}.height('100%')}
}@Component
struct Nav {title: string = ""@BuilderParam left: () => void@BuilderParam right: () => voidbuild() {Row() {this.left()Text(this.title)this.right()}.width("100%").justifyContent(FlexAlign.SpaceBetween)}
}@Component
struct list {title: string = ""@BuilderParam list1:()=>voidbuild() {Row() {this.list1()}.width("100%").height(89).margin({ top: 10 }).justifyContent(FlexAlign.SpaceBetween).backgroundColor(Color.Gray)}
}
二、生命周期
页面生命周期:
即被@Entry装饰的组件生命周期。提供以下生命周期接口:
onPageShow: 页面每次显示时触发一次,包括路由过程、应用进入前台等场景,仅@Entry装饰的自定义组件生效。
onPageHide: 页面每次隐藏时触发一次,包括路由过程、应用进入前后台等场景,仅@Entry装饰的自定义组件生效。
onBackPress:当用户点击返回按时触发,仅@Entry装饰的自定义组件生效。
组件生命周期
即一般用@Component装饰的自定义组件的生命周期,提供以下生命周期接口:
aboutToAppear: 组件即将出现时回调该接口,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。
aboutToDisappear: 在自定义组件析构销毁之前执行。不允许在aboutToDisappear函数中改变状态变量,特别是@Link变量的修改可能会导致应用程序行为不稳定。
简单举例说明:
@Entry
@Component
struct PageLife {@State message: string = 'Hello World'@State isShow: boolean = true;// 页面准备-可以网络请求aboutToAppear() {console.log("aboutToAppear")}// 页面显示onPageShow() {console.log("onPageShow")}// 页面离开onPageHide() {console.log("onPageHide")}// 返回按钮onBackPress() {console.log("onBackPress")}// 页面销毁aboutToDisappear() {console.log("aboutToDisappear")}build() {Row() {Column() {Text("爆炸现场").fontSize(50).fontWeight(FontWeight.Bold)if (this.isShow) {Boob({isShow:$isShow})} else {Button("已爆炸")}}.width('100%')}.height('100%')}
}@Component
struct Boob {@Link isShow:boolean@State count: number = 10timer: number = 0aboutToAppear() {this.timer=setInterval(() => {this.count--// this.isShow为false时,该组件销毁====》调用aboutToDisappear方法。if(this.count===0){this.isShow=false}console.log(this.count+"")}, 1000)}aboutToDisappear() {clearInterval(this.timer)}build() {Column() {Button("倒计时")Text(this.count+" S").fontSize(20)}}
}
三、页面路由
页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOs提供了Router模块,通过不同的ur地址,可以方便地进行页面路由,轻松地访问不同的页面。
Router模块提供了两种跳转模式,分别是router.pushUrl()和router.replaceUrl()。这两种模式决定了目标页是否会替换当前页。
router.pushUrl(): 目标页不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用router.back()方法返回到当前页。
router.replaceUrl(): 目标页会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。
并且Router模块提供了两种实例模式,分别是Standard和Single。这两种模式决定了目标url是否会对应多个实例
Standard: 标准模式,也是默认情况下的实例模式。每次调用该方法都会新建一个目标页,并压入栈顶。
Single: 单例模式。即如果目标页的url在页面栈中已经存在同ur页面,则离栈顶最近的同url页面会被移动到栈顶,并重新加载,如果目标页的url在页面栈中不存在同url页面,则按照标准模式跳转。
router.pushUrl()——>Standard A跳转到B,栈中有B,还是新建B,A压入栈中,B在A上。
router.pushUrl()——>Single A跳转到B,栈中有B,不新建B,A压入栈中,已有B提至A上。
router.replaceUrl()——>Standard A跳转到B,栈中有B,还是新建B,销毁A。B置于栈顶。
router.replaceUrl()——>Single A跳转到B,栈中有B,不新建B,销毁A,已有B提至栈顶。
import router from '@ohos.router'@Entry
@Component
struct PageRouter {@State message: string = '努力方向'@State list: Object[] = [{id: 1,name: "房子"}, { id: 2, name: "车子" }, { id: 3, name: "金条" }]build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)List() {ForEach(this.list, item => {ListItem() {Text(item.name).fontSize(40).margin({top:10}).fontColor(Color.Orange)}.width('100%').onClick(()=>{router.pushUrl({url:'pages/PageRouterDetail',params:{id:item.id,name:item.name}},router.RouterMode.Standard)})})}}.width('100%')}.height('100%')}onPageShow(){const param=router.getParams();console.log("PageRouter-onPageShow",JSON.stringify(param))}
}
import router from '@ohos.router'@Entry
@Component
struct PageRouterDetail {@State message: string = '拿到'name: stringaboutToAppear() {const param = router.getParams()const jsp=JSON.stringify(param)console.log("D_aboutToAppear", jsp)this.name=JSON.parse(jsp).nameconsole.log("D_aboutToAppear", this.name )}build() {Row() {Column() {Text(this.name).fontSize(50).fontWeight(FontWeight.Bold)Button("返回").onClick(() => {this.onReturn1()})}.width('100%')}.height('100%')}onReturn1() {router.showAlertBeforeBackPage({message:'确定要返回吗?'})router.back({url:"pages/PageRouter",params:{id:4,name:"我发财了"}})}
}
四、程序入口
UIAbility是一种包含用户界面的应用组件,主要用于和用户进行交互。UIAbility也是系统调度的单元,为应用提供窗口在其中绘制界面。
每一个UIAbility实例,都对应于一个最近任务列表中的任务。
UIAbility生命周期
UIAbility是在module.json5里面配置的。
import common from '@ohos.app.ability.common'
@Entry
@Component
struct PageEntry {@State message: string = 'Hello World'private context =getContext(this) as common.UIAbilityContextbuild() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)Button("跳转ability").onClick(()=>{let want={deviceId:"",bundleName:getContext(this.context).applicationInfo.name,//获得包名abilityName:"MoneyAbility",parameters:{name:"随便拿,都是你的了"}}this.context.startAbility(want)})}.width('100%')}.height('100%')}
}
@Entry
@Component
struct PageMoney {@State message: string = '金子银子随便拿'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}
{"module": {"name": "entry","type": "entry","description": "$string:module_desc","mainElement": "EntryAbility","deviceTypes": ["phone","tablet"],"deliveryWithInstall": true,"installationFree": false,"pages": "$profile:main_pages","abilities": [{"name": "EntryAbility","srcEntry": "./ets/entryability/EntryAbility.ts","description": "$string:EntryAbility_desc","icon": "$media:icon","label": "$string:EntryAbility_label","startWindowIcon": "$media:icon","startWindowBackground": "$color:start_window_background","exported": true,"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}]},{"name": "MoneyAbility","srcEntry": "./ets/MoneyAbility/MoneyAbility.ts","description": "$string:EntryAbility_desc","icon": "$media:icon","label": "$string:EntryAbility_label","startWindowIcon": "$media:icon","startWindowBackground": "$color:start_window_background","exported": true}]}
}
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';export default class MoneyAbility extends UIAbility {onCreate(want, launchParam) {console.log("MoneyAbility--",want?.parameters?.name)hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');}onDestroy() {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');}onWindowStageCreate(windowStage: window.WindowStage) {// Main window is created, set main page for this abilityhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');AppStorage.SetOrCreate("name","房子")windowStage.loadContent('pages/PageMoney',(err, data) => {if (err.code) {hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');return;}hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');});}onWindowStageDestroy() {// Main window is destroyed, release UI related resourceshilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground() {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground() {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}