上一节已完成内容区域界面,通过页面状态管理@state @prop实现了组件间页面数据的传输,这一节,我们完善列表功能。
=> 实现一个简单的列表功能
@Component
export default struct TargetList {
targetData: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
build() {
Column() {
Row() {
Text('子目标')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#182431')
}
.width('100%')
.height(30)
.padding({ left: 16, right: 11 })
List({ space: 5 }) {
ForEach(this.targetData, (item: string, index: number) => {
ListItem() {
Text(item)
.height(30)
.width('100%')
.textAlign(TextAlign.Center)
.backgroundColor(Color.Pink)
}
}, (item: string) => JSON.stringify(item))
}
.edgeEffect(EdgeEffect.None)
.margin({ top: 12 })
.width('100%')
.height('80%')
Blank()
Button('添加子目标')
.operateButtonStyle('#007dff')
.onClick(() => {
prompt.showToast({
message:'按钮被点击了',
duration:1000
})
})
}
.width('93.3%')
.height('100%')
.padding({ top: 16 })
}
}
@Extend(Button) function operateButtonStyle(color: string) {
.width(156)
.height(40)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(color)
.backgroundColor('#0d182431')
}
效果图如下:
那么问题来了,这里有一个button按钮,子组件的按钮点击事件怎么可以让父组件调用呢?
事件回调
import prompt from '@ohos.prompt'
@Component
export default struct TargetList {
targetData: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
onAddClick?: () => void
build() {
Column() {
...
Button('添加子目标')
.operateButtonStyle('#007dff')
.onClick(() => {
this.onAddClick()
})
}
...
}
}
...
}
在index父组件中调用子组件
import prompt from '@ohos.prompt'
import TargetInformation from '../view/TargetInformation'
import TargetList from '../view/TargetList'
@Entry
@Component
struct Index {
@State latestUpdateDate: string = '2023-12-13 23:00'
@State totalTasksNumber: number = 3
@State completedTasksNumber: number = 1
build() {
Column() {
...
//List列表
TargetList({
onAddClick:()=>prompt.showToast({
message:'现在是父组件调用button',
duration:1000
})
})
.height('67%')
}
...
}
...
}
现在点击按钮,你会发现,父组件响应了该事件弹出提示框。
=> 实现弹窗,先搭架子
import prompt from '@ohos.prompt'
import TargetInformation from '../view/TargetInformation'
import TargetList from '../view/TargetList'
@Entry
@Component
struct Index {
@State latestUpdateDate: string = '2023-12-13 23:00'
@State totalTasksNumber: number = 3
@State completedTasksNumber: number = 1
dialogController: CustomDialogController = new CustomDialogController({
builder: () => prompt.showToast({
message: '现在是在弹窗调用button',
duration: 1000
}),
alignment: DialogAlignment.Bottom,
offset: {
dx: 0,
dy: -16
},
customStyle: true,
autoCancel: false
})
build() {
Column() {
...
//List列表
TargetList({
onAddClick: () => this.dialogController.open()
})
.height('67%')
}
...
}
...
}
=> 实现弹窗,画弹窗界面
新建AddTargetDialog类,需要添加@CustomDialog注解,注意此处不是添加组件,因此不是添加@Component!!!
import prompt from '@ohos.prompt'
import AddTargetDialog from '../view/AddTargetDialog'
import TargetInformation from '../view/TargetInformation'
import TargetList from '../view/TargetList'
@Entry
@Component
struct Index {
@State latestUpdateDate: string = '2023-12-13 23:00'
@State totalTasksNumber: number = 3
@State completedTasksNumber: number = 1
dialogController: CustomDialogController = new CustomDialogController({
builder: AddTargetDialog(),
alignment: DialogAlignment.Bottom,
offset: {
dx: 0,
dy: -16
},
customStyle: true,
autoCancel: false
});
...
...
}
@CustomDialog
export default struct AddTargetDialog {
/**
* @CustomDialog component should have a property of the CustomDialogController type.
* @CustomDialog组件应具有CustomDialogController类型的属性。
*/
private controller?: CustomDialogController;
build() {
Column() {
Text('添加子目标')
}
.height(168)
.width('90.3%')
.padding(24)
.borderRadius(32)
.backgroundColor(Color.White)
}
}
此时,弹窗出现了,继续优化弹窗界面
import prompt from '@ohos.prompt';
@CustomDialog
export default struct AddTargetDialog {
/**
* @CustomDialog component should have a property of the CustomDialogController type.
* @CustomDialog组件应具有CustomDialogController类型的属性。
*/
private controller?: CustomDialogController;
onClickOk?: (value: string) => void
build() {
Column() {
Text('添加子目标')
.width('100%')
.fontSize(20)
.fontColor('#182431')
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Start)
TextInput({ placeholder: '请输入子目标名称' })
.placeholderColor(Color.Gray)
.placeholderFont({ size: 16 })
.caretColor(Color.Blue) //光标的颜色
.backgroundColor('$0d182431')
.width('100%')
.height('40%')
.margin({ top: '6%' })
.fontSize(16)
.fontColor('#182431')
Blank()
Row() {
Button('取消')
.dialogButtonStyle()
.width('50%')
.onClick(() => {
this.controller.close()
})
Divider().vertical(true)
Button('确定')
.dialogButtonStyle()
.width('50%')
.onClick(() => {
prompt.showToast({
message:'点击了确定'
})
})
}
.width('100%')
.height('10%')
.justifyContent(FlexAlign.Center)
}
.height(168)
.width('90.3%')
.padding(24)
.borderRadius(32)
.backgroundColor(Color.White)
}
}
@Extend(Button) function dialogButtonStyle() {
.fontSize(16)
.height(32)
.width(96)
.backgroundColor(Color.White)
.fontColor("#007dff")
}
此时,点击取消,弹窗消息,点击确定,出现提示框。
那么问题来了,我们现在需要点击确定,获取输入框的文字,点击确定后,传递给父组件
=> 继续完善代码
@CustomDialog
export default struct AddTargetDialog {
...
@State subTaskName:string = ''
build() {
Column() {
...
TextInput({ placeholder: '请输入子目标名称' })
...
//添加输入框文本监听事件
.onChange((value:string)=>{
this.subTaskName = value
})
Blank()
Row() {
...
Button('确定')
.dialogButtonStyle()
.width('50%')
.onClick(() => {
//获取输入框文本
prompt.showToast({
message:this.subTaskName
})
})
}
...
}
...
}
}
...
现在点击确定,toast提示框则提示输入框中的文字。
思考:list数组在TargetList组件,添加数组在AddTargetDialog弹窗界面,他们数据怎么做到互通呢?
回答:通过父组件容器!!!
import prompt from '@ohos.prompt'
@Component
export default struct TargetList {
@Link targetData: string[] //添加@link与父组件进行绑定
onAddClick?: () => void
...
}
...
import prompt from '@ohos.prompt'
import AddTargetDialog from '../view/AddTargetDialog'
import TargetInformation from '../view/TargetInformation'
import TargetList from '../view/TargetList'
@Entry
@Component
struct Index {
@State latestUpdateDate: string = '2023-12-13 23:00'
@State totalTasksNumber: number = 3
@State completedTasksNumber: number = 1
@State targetData: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
build() {
Column() {
...
//List列表
TargetList({
targetData: $targetData, //这里需要使用$符号,被@link装饰的不能用this
onAddClick: () => this.dialogController.open()
})
.height('67%')
}
...
}
...
}
}
点击添加子目标按钮,将数据传递到list中
import prompt from '@ohos.prompt'
import AddTargetDialog from '../view/AddTargetDialog'
import TargetInformation from '../view/TargetInformation'
import TargetList from '../view/TargetList'
@Entry
@Component
struct Index {
@State latestUpdateDate: string = '2023-12-13 23:00'
@State totalTasksNumber: number = 3
@State completedTasksNumber: number = 1
@State targetData: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
dialogController: CustomDialogController = new CustomDialogController({
builder: AddTargetDialog({
onClickOk:(value:string):void => this.saveTask(value)
}),
alignment: DialogAlignment.Bottom,
offset: {
dx: 0,
dy: -16
},
customStyle: true,
autoCancel: false
});
saveTask(taskName:string){
this.targetData.push(taskName)
this.dialogController.close()
}
build() {
Column() {
...
//List列表
TargetList({
targetData: $targetData,
onAddClick: () => this.dialogController.open()
})
.height('67%')
}
...
}
...
}
效果图如下,我们已经将数据添加到list数组中。
下一步,我们将对list的item进行完善。