简单的组件学习:
/** * weip 自定义控件 * 自定义构建函数也是需要充电的地方,分全局和局部的 * 全局:需要添加function关键字 局部:不加function关键字 * @Styles function 自定义公共样式 分全局和局部 * @Extends(Text) 继承模式 只能写成全局的 * export:导出组件 */ @Component export struct Header { private title: ResourceStr; build() { // 标题部分 Row() { // 资源自行替换,返回icon Image($r('app.media.app_icon')) .width(30) Text(this.title) .fontSize(30) .fontWeight(FontWeight.Bold) Blank() // 资源自行替换,分享icon Image($r('app.media.app_icon')) .width(30) } .width('100%') .height(30) } }
ImagesPage.ets:
引用header组件
/** * 导入head组件 */ import { Header } from '../components/HeadComponents' // 全局自定义构建函数 function:代表全局 @Builder function ItemCard() { } // 组件内的局部函数需要加this // 自定义公共样式 @Styles function fillScreen() { .width('100%') .height('100%') .backgroundColor('#EFEFEF') .padding(20) } // 自定义字体样式 需使用Extend() 继承模式,只能写在全局位置 @Extend(Text) function priceText() { .fontSize(18) .fontColor('#F36') } @Entry @Component struct Index { @State imageWidth: number = 150 // ForEach:循环遍历数组,根据数组内容渲染页面组件,超过屏幕的东西就看不到,也滑动不了,所以后面统一使用List组件 build() { // 纵向布局 主轴/交叉轴,一般只设置主轴,不设置交叉轴 Column() { // 标题 Header({title: "图片详情"}) .padding({left: 20, top: 20, right: 20, bottom: 20}) // 横向布局 主轴/交叉轴,一般只设置主轴,不设置交叉轴 Row(){ Image($r('app.media.icon')) .width(this.imageWidth) .interpolation(ImageInterpolation.High) } .width('100%') .height(400) .justifyContent(FlexAlign.Center) // Row容器 放一行 Row() { Text($r('app.string.width_label')) .fontSize(20) .fontWeight(FontWeight.Bold) .fontColor('#663') TextInput({ placeholder: '请输入图片宽度', text:this.imageWidth.toFixed(0) }) .width(150) .backgroundColor('#FFF') .type(InputType.Number) .onChange(value => { console.log(value) this.imageWidth = parseInt(value) }) } .width('100%') .padding({left: 14,right: 14}) .justifyContent(FlexAlign.SpaceBetween) // 中间留空 // 分割线 Divider() .width('91%') // 两个按钮 Row(){ Button('缩小') .width(80) .fontSize(20) .onClick(() => { if (this.imageWidth >= 10) { this.imageWidth -= 10; } }) Button('放大') .width(80) .fontSize(20) .onClick(() => { if (this.imageWidth < 300) { this.imageWidth += 10; } }) } .width('100%') .margin({top: 35, bottom: 35}) .justifyContent(FlexAlign.SpaceEvenly) Slider({ min: 100, max: 300, value: this.imageWidth, step: 10 }) .width('100%') .blockColor('#36D') .trackThickness(7) .showTips(true) .onChange(value => { // value:当前滑块值 this.imageWidth = value; }) } .width('100%') .height('100%') } } /** * struct:自定义组件 可复用的UI单元 * 装饰器:用来装饰类结构、方法、变量 * @Component:标记自定义组件 * @Entry:标记当前组件是入口组件 * @State:标记一个变量是状态变量,值变化时会触发UI更新 * build():UI描述,其内部以声明式方式描述UI结构 * 内置组件:ArkUI提供的组件,比如容器组件如Row、Column * 基础组件:自带样式和功能的页面元素,如Text * 属性方法:设置组件的UI样式 * 事件方法:设置组件的事件回调 * 组件通用属性、特有属性(图片插值) */
Index.ets:
一般是应用程序的入口
@Entry // 入口組件 @Component struct Index { @State message: string = 'Hello World' build() { Row() { Column() { Text(this.message) .fontSize(50) .fontWeight(FontWeight.Bold) .fontColor('#36D') .onClick(() => { this.message = 'Hello ArkTS!'; }) // Image('https://bkimg.cdn.bcebos.com/pic/bd315c6034a85edf8db139b7db031e23dd54564edf55?x-bce-process=image/format,f_auto/quality,Q_70/resize,m_lfit,limit_1,w_536') // .width('50%') // 引用本地图片资源地址 Image($r('app.media.icon')) .width(250) .interpolation(ImageInterpolation.High) } .width('100%') } .height('100%') } } /** * struct:自定义组件 可复用的UI单元 * 装饰器:用来装饰类结构、方法、变量 * @Component:标记自定义组件 * @Entry:标记当前组件是入口组件 * @State:标记一个变量是状态变量,值变化时会触发UI更新 * build():UI描述,其内部以声明式方式描述UI结构 * 内置组件:ArkUI提供的组件,比如容器组件如Row、Column * 基础组件:自带样式和功能的页面元素,如Text * 属性方法:设置组件的UI样式 * 事件方法:设置组件的事件回调 * 组件通用属性、特有属性(图片插值) */
PropPage.ets:
/** * 自定义任务类 */ class Task { // 静态变量,所有对象共享变量 static id: number = 1 // 任务名称 半角:`` name: string = `任务${Task.id++}` // 任务状态:是否完成 finished: boolean = false } // 统一的卡片样式 @Styles function card() { .width('95%') .padding(20) .backgroundColor(Color.White) .borderRadius(15) .shadow({radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4}) } // 任务完成样式 @Extend(Text) function finishedTask() { .decoration({type: TextDecorationType.LineThrough}) .fontColor('#B1B2B1') } // 任务统计信息的实体类【c】 class StaticInfo { totalTask: number = 0; finishTask: number = 0; } @Entry @Component struct PropPage { // 总任务数量 @State totalTask: number = 0 // 已完成任务数量 @State finishTask: number = 0 build() { Column({space: 10}){ // 任务进度卡片 子组件 TaskStatistics({finishTask:this.finishTask, totalTask: this.totalTask}) // 任务列表,包含新增任务 @Link totalTask:$finishTask:变量的引用 TaskList({finishTask:$finishTask, totalTask: $totalTask}) } .width('100%') .height('100%') .backgroundColor('#F1F2F3') } } @Component struct TaskList { // 总任务数量 @Link totalTask: number // 已完成任务数量 @Link finishTask: number // 任务数组 @State tasks: Task[] = [] handleTaskChange(){ // 更新任务总数量 this.totalTask = this.tasks.length // 更新已完成任务数量 this.finishTask = this.tasks.filter(item => item.finished).length } build() { Column() { // 2、新增任务按钮 Button('新增任务') .width(200) .onClick(() => { // 新增任务数据 this.tasks.push(new Task()) // 更新任务总数量 this.handleTaskChange() }) // 3、任务列表 List({space: 10}) { ForEach( this.tasks, (item: Task, index) => { ListItem() { Row() { // 任务名 Text(item.name) .fontSize(20) // 任务复选框 Checkbox() .select(item.finished) .onChange(isSelected => { // 任务状态发生变更,更新当前任务状态 item.finished = isSelected // 更新已完成任务数量 this.handleTaskChange() }) } .card() .justifyContent(FlexAlign.SpaceBetween) } .swipeAction({end: this.DeleteButton(index)}) } ) } .width('100%') .layoutWeight(1) .alignListItem(ListItemAlign.Center) } } @Builder DeleteButton(index: number) { Button(){ Image($r('app.media.icon')) .fillColor(Color.White) .width(20) } .width(40) .height(40) .type(ButtonType.Circle) .backgroundColor(Color.Red) .margin(5) .onClick(() => { // 从角标开始删 删1个 this.tasks.splice(index, 1) this.handleTaskChange() }) } } /** * 任务进度卡片 子组件 * 子组件是TaskStatistics 此时父组件是PropPage.ets * Prop:变量不能初始化 单向同步【父组件-->子组件】 * Link:支持传对象 Prop:不支持传对象 * provider 跨组件传输 * consume 跨组件传输 */ @Component struct TaskStatistics { // 总任务数量 @Prop totalTask: number // 已完成任务数量 @Prop finishTask: number build() { Row() { // 任务进度 Text('任务进度') .fontSize(30) .fontWeight(FontWeight.Bold) // 堆叠容器 Stack() { // 进度条 Progress({ value: this.finishTask, total: this.totalTask, type: ProgressType.Ring }) // 1/5 Row() { Text(this.finishTask.toString()) .fontSize(24) .fontColor('#36D') Text(' / ' + this.totalTask.toString()) .fontSize(24) } } } .card() .margin({top: 20, bottom: 20}) .justifyContent(FlexAlign.SpaceEvenly) } }
预览效果图:
注解的学习:
/** * 自定义任务类 */ class Task { // 静态变量,所有对象共享变量 static id: number = 1 // 任务名称 半角:`` name: string = `任务${Task.id++}` // 任务状态:是否完成 finished: boolean = false } // 统一的卡片样式 @Styles function card() { .width('95%') .padding(20) .backgroundColor(Color.White) .borderRadius(15) .shadow({radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4}) } // 任务完成样式 @Extend(Text) function finishedTask() { .decoration({type: TextDecorationType.LineThrough}) .fontColor('#B1B2B1') } // 任务统计信息的实体类 class StatInfo { totalTask: number = 0; finishTask: number = 0; } /** * 父组件 */ @Entry @Component struct PropPage { // 统计信息 【父亲】 @State stat: StatInfo = new StatInfo() build() { Column({space: 10}){ // 任务进度卡片 子组件 TaskStatistics({finishTask:this.stat.finishTask, totalTask: this.stat.totalTask}) // 任务列表,包含新增任务 @Link totalTask:$finishTask:变量的引用 TaskList({stat:$stat}) } .width('100%') .height('100%') .backgroundColor('#F1F2F3') } } @Component struct TaskList { // 统计信息【儿子】 Link可以传对象 @Link stat: StatInfo // 任务数组 @State tasks: Task[] = [] handleTaskChange(){ // 更新任务总数量 this.stat.totalTask = this.tasks.length // 更新已完成任务数量 this.stat.finishTask = this.tasks.filter(item => item.finished).length } build() { Column() { // 2、新增任务按钮 Button('新增任务') .width(200) .onClick(() => { // 新增任务数据 this.tasks.push(new Task()) // 更新任务总数量 this.handleTaskChange() }) // 3、任务列表 List({space: 10}) { ForEach( this.tasks, (item: Task, index) => { ListItem() { Row() { // 任务名 Text(item.name) .fontSize(20) // 任务复选框 Checkbox() .select(item.finished) .onChange(isSelected => { // 任务状态发生变更,更新当前任务状态 item.finished = isSelected // 更新已完成任务数量 this.handleTaskChange() }) } .card() .justifyContent(FlexAlign.SpaceBetween) } .swipeAction({end: this.DeleteButton(index)}) } ) } .width('100%') .layoutWeight(1) .alignListItem(ListItemAlign.Center) } } @Builder DeleteButton(index: number) { Button(){ Image($r('app.media.icon')) .fillColor(Color.White) .width(20) } .width(40) .height(40) .type(ButtonType.Circle) .backgroundColor(Color.Red) .margin(5) .onClick(() => { // 从角标开始删 删1个 this.tasks.splice(index, 1) this.handleTaskChange() }) } } /** * 任务进度卡片 子组件 * 子组件是TaskStatistics 此时父组件是PropPage.ets * Prop:变量不能初始化 单向同步【父组件-->子组件】 * Link:支持传对象 Prop:不支持传对象 * provider 跨组件传输 * consume 跨组件传输 */ @Component struct TaskStatistics { // 总任务数量 @Prop totalTask: number // 已完成任务数量 @Prop finishTask: number build() { Row() { // 任务进度 Text('任务进度') .fontSize(30) .fontWeight(FontWeight.Bold) // 堆叠容器 Stack() { // 进度条 Progress({ value: this.finishTask, total: this.totalTask, type: ProgressType.Ring }) // 1/5 Row() { Text(this.finishTask.toString()) .fontSize(24) .fontColor('#36D') Text(' / ' + this.totalTask.toString()) .fontSize(24) } } } .card() .margin({top: 20, bottom: 20}) .justifyContent(FlexAlign.SpaceEvenly) } }
跨组件传输数据:
@Provider @Consume
这种相对比较费内存,非跨组件不建议使用
/** * 自定义任务类 */ class Task { // 静态变量,所有对象共享变量 static id: number = 1 // 任务名称 半角:`` name: string = `任务${Task.id++}` // 任务状态:是否完成 finished: boolean = false } // 统一的卡片样式 @Styles function card() { .width('95%') .padding(20) .backgroundColor(Color.White) .borderRadius(15) .shadow({radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4}) } // 任务完成样式 @Extend(Text) function finishedTask() { .decoration({type: TextDecorationType.LineThrough}) .fontColor('#B1B2B1') } // 任务统计信息的实体类 class StatInfo { totalTask: number = 0; finishTask: number = 0; } /** * 父组件 */ @Entry @Component struct PropPage { // 统计信息 【父亲】 @Provide stat: StatInfo = new StatInfo() build() { Column({space: 10}){ // 任务进度卡片 子组件 TaskStatistics() // 任务列表,包含新增任务 @Link totalTask:$finishTask:变量的引用 TaskList() } .width('100%') .height('100%') .backgroundColor('#F1F2F3') } } @Component struct TaskList { // 统计信息【儿子】 Link可以传对象 @Consume stat: StatInfo // 任务数组 @State tasks: Task[] = [] handleTaskChange(){ // 更新任务总数量 this.stat.totalTask = this.tasks.length // 更新已完成任务数量 this.stat.finishTask = this.tasks.filter(item => item.finished).length } build() { Column() { // 2、新增任务按钮 Button('新增任务') .width(200) .onClick(() => { // 新增任务数据 this.tasks.push(new Task()) // 更新任务总数量 this.handleTaskChange() }) // 3、任务列表 List({space: 10}) { ForEach( this.tasks, (item: Task, index) => { ListItem() { Row() { // 任务名 Text(item.name) .fontSize(20) // 任务复选框 Checkbox() .select(item.finished) .onChange(isSelected => { // 任务状态发生变更,更新当前任务状态 item.finished = isSelected // 更新已完成任务数量 this.handleTaskChange() }) } .card() .justifyContent(FlexAlign.SpaceBetween) } .swipeAction({end: this.DeleteButton(index)}) } ) } .width('100%') .layoutWeight(1) .alignListItem(ListItemAlign.Center) } } @Builder DeleteButton(index: number) { Button(){ Image($r('app.media.icon')) .fillColor(Color.White) .width(20) } .width(40) .height(40) .type(ButtonType.Circle) .backgroundColor(Color.Red) .margin(5) .onClick(() => { // 从角标开始删 删1个 this.tasks.splice(index, 1) this.handleTaskChange() }) } } /** * 任务进度卡片 子组件 * 子组件是TaskStatistics 此时父组件是PropPage.ets * Prop:变量不能初始化 单向同步【父组件-->子组件】 * Link:支持传对象 Prop:不支持传对象 * provider 跨组件传输 * consume 跨组件传输 */ @Component struct TaskStatistics { // 统计信息 @Consume stat: StatInfo build() { Row() { // 任务进度 Text('任务进度') .fontSize(30) .fontWeight(FontWeight.Bold) // 堆叠容器 Stack() { // 进度条 Progress({ value: this.stat.finishTask, total: this.stat.totalTask, type: ProgressType.Ring }) // 1/5 Row() { Text(this.stat.finishTask.toString()) .fontSize(24) .fontColor('#36D') Text(' / ' + this.stat.totalTask.toString()) .fontSize(24) } } } .card() .margin({top: 20, bottom: 20}) .justifyContent(FlexAlign.SpaceEvenly) } }
// bind(this)
/** * 自定义任务类 */ @Observed class Task { // 静态变量,所有对象共享变量 static id: number = 1 // 任务名称 半角:`` name: string = `任务${Task.id++}` // 任务状态:是否完成 finished: boolean = false } // 统一的卡片样式 @Styles function card() { .width('95%') .padding(20) .backgroundColor(Color.White) .borderRadius(15) .shadow({radius: 6, color: '#1F000000', offsetX: 2, offsetY: 4}) } // 任务完成样式 @Extend(Text) function finishedTask() { .decoration({type: TextDecorationType.LineThrough}) .fontColor('#B1B2B1') } // 任务统计信息的实体类 class StatInfo { totalTask: number = 0; finishTask: number = 0; } /** * 父组件 */ @Entry @Component struct PropPage { // 统计信息 【父亲】 @Provide stat: StatInfo = new StatInfo() build() { Column({space: 10}){ // 任务进度卡片 子组件 TaskStatistics() // 任务列表,包含新增任务 @Link totalTask:$finishTask:变量的引用 TaskList() } .width('100%') .height('100%') .backgroundColor('#F1F2F3') } } @Component struct TaskList { // 统计信息【儿子】 Link可以传对象 @Consume stat: StatInfo // 任务数组 @State tasks: Task[] = [] handleTaskChange(){ // 更新任务总数量 this.stat.totalTask = this.tasks.length // 更新已完成任务数量 this.stat.finishTask = this.tasks.filter(item => item.finished).length } build() { Column() { // 2、新增任务按钮 Button('新增任务') .width(200) .onClick(() => { // 新增任务数据 this.tasks.push(new Task()) // 更新任务总数量 this.handleTaskChange() }) // 3、任务列表 List({space: 10}) { ForEach( this.tasks, (item: Task, index) => { ListItem() { // bind(this) 绑定父组件的this TaskItem({item: item, onTaskChange: this.handleTaskChange.bind(this)}) } .swipeAction({end: this.DeleteButton(index)}) } ) } .width('100%') .layoutWeight(1) .alignListItem(ListItemAlign.Center) } } @Builder DeleteButton(index: number) { Button(){ Image($r('app.media.icon')) .fillColor(Color.White) .width(20) } .width(40) .height(40) .type(ButtonType.Circle) .backgroundColor(Color.Red) .margin(5) .onClick(() => { // 从角标开始删 删1个 this.tasks.splice(index, 1) this.handleTaskChange() }) } } /** * 自定义任务的item项 * 方法传递 */ @Component struct TaskItem { @ObjectLink item: Task // 变量的类型是个函数类型 onTaskChange: () => void build() { Row() { // 任务名 如果完成,需要变灰 if (this.item.finished) { Text(this.item.name) .fontSize(20) .finishedTask() } else { Text(this.item.name) .fontSize(20) } // 任务复选框 Checkbox() .select(this.item.finished) .onChange(isSelected => { // 任务状态发生变更,更新当前任务状态 this.item.finished = isSelected // 更新已完成任务数量 //this.handleTaskChange() this.onTaskChange() }) } .card() .justifyContent(FlexAlign.SpaceBetween) } } /** * 任务进度卡片 子组件 * 子组件是TaskStatistics 此时父组件是PropPage.ets * Prop:变量不能初始化 单向同步【父组件-->子组件】 * Link:支持传对象 Prop:不支持传对象 * provider 跨组件传输 * consume 跨组件传输 */ @Component struct TaskStatistics { // 统计信息 @Consume stat: StatInfo build() { Row() { // 任务进度 Text('任务进度') .fontSize(30) .fontWeight(FontWeight.Bold) // 堆叠容器 Stack() { // 进度条 Progress({ value: this.stat.finishTask, total: this.stat.totalTask, type: ProgressType.Ring }) // 1/5 Row() { Text(this.stat.finishTask.toString()) .fontSize(24) .fontColor('#36D') Text(' / ' + this.stat.totalTask.toString()) .fontSize(24) } } } .card() .margin({top: 20, bottom: 20}) .justifyContent(FlexAlign.SpaceEvenly) } }