前言:我们自定义组件的时候,有时候需要传递大量的参数,父组件给子组件传值的时候需要很多参数,就需要每个参数都要写一遍,但是我在看系统的高级组件的时候,它的组件写法很值得我们去学习。那如何优雅的实现自定义组件呢?下面就先看看系统的高级组件的写法。
举例:
它采用的prop形容组件,这个是状态变量的修饰符。
官方解释:
Prop变量允许在本地修改,但修改后的变化不会同步回父组件。
当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件。
传递的是待实现的类,我们可以模仿系统的写法自定义自己需要的组件
以及定义一些class,通过class对象传值
SubHeader
export declare struct SubHeader {
@Prop
icon?: ResourceStr;
iconSymbolOptions?: SymbolOptions;
@Prop
primaryTitle?: ResourceStr;
@Prop
secondaryTitle?: ResourceStr;
select?: SelectOptions;
/**
* Operation style of SubHeader.
* @type { OperationStyle }.
* @syscap SystemCapability.ArkUI.ArkUI.Full
* @since 10
*/
/**
* Operation style of SubHeader.
* @type { OperationStyle }.
* @syscap SystemCapability.ArkUI.ArkUI.Full
* @atomicservice
* @since 11
*/
@Prop
operationType?: OperationType;
operationItem?: Array<OperationOption>;
operationSymbolOptions?: Array<SymbolOptions>;
primaryTitleModifier?: TextModifier;
secondaryTitleModifier?: TextModifier;
@BuilderParam
titleBuilder?: () => void;
@Prop
contentPadding?: LocalizedPadding;
}
export declare class SelectOptions {
options: Array<SelectOption>;
selected?: number;
value?: string;
onSelect?: (index: number, value?: string) => void;
}
使用方法
SubHeader({
select: {
options: [{ value: 'aaa' }, { value: 'bbb' }, { value: 'ccc' }],
value: 'selectdemo',
selected: 2,
onSelect: (index: number, value?: string) => {
promptAction.showToast({ message: 'demo' })
}
},
operationType: OperationType.ICON_GROUP,
operationItem: [{
value: $r('app.media.startIcon'),
action: () => {
promptAction.showToast({ message: 'demo' })
}
}]
效果图:
官方写的是不是很优雅,那我们就模仿它的写法自定义组件
通过不同的参数传递控制实现不同的样式UI
但是看不到具体的实现方法。我们只能猜测他们的内部写法。
结语:
系统的组件定义方法值得我们学习,使用系统组件的时候,也有学习的地方,是用Attribuite来定义扩展方法,使用起来更优雅美观,比我们写一大堆系统组件的设置方法优雅美观。这是我自定义的一个组件,
import { ImageModifier, TextModifier, WinImageLabel, WinImageLabelType } from './WinImageLabel';
export declare class DropDownSelectOptions{
options?: Array<SelectOption>;
selected?: number;
value?: string;
icon?:Resource;
selectIcon?:Resource;
onSelect?: (index: number, value?: string) => void;
popType?:string;
}
@Component
export struct WinDropDownItem{
imageAttribute:ImageModifier = new ImageModifier(14,7)
textAttribute:TextModifier = new TextModifier('#000',14)
@Prop
select?: DropDownSelectOptions;
@State customPopup: boolean = false
@Link selectedDate?: Date;
@Link selectDate?:string;
build() {
RelativeContainer(){
Text(this.select?.value)
.attributeModifier(this.textAttribute)
.id('title')
.alignRules({
center:{anchor:'__container__',align:VerticalAlign.Center},
left:{anchor:'__container__',align:HorizontalAlign.Start},
})
.height(18)
Image(this.customPopup?this.select?.selectIcon:this.select?.icon)
.attributeModifier(this.imageAttribute)
.id('icon')
.alignRules({
center:{anchor:'__container__',align:VerticalAlign.Center},
left:{anchor:'title',align:HorizontalAlign.End},
})
.margin({left:2})
}
.onClick(()=>{
this.customPopup = !this.customPopup;
if (this.select?.popType == 'date') {
DatePickerDialog.show({
start: new Date("2000-1"),
end: new Date("2030-12"),
selected: this.selectedDate,
lunar: false,
disappearTextStyle: {color: '#efefef', font: {size: '16fp'}},
textStyle: {color: '#e0e0e0', font: {size: '18fp', weight: FontWeight.Normal}},
selectedTextStyle: {color: '#ff182431', font: {size: '14fp', weight: FontWeight.Regular}},
alignment:DialogAlignment.Bottom,
onDateAccept: (value: Date) => {
this.selectedDate = value
console.info("DatePickerDialog:onDateAccept()" + value.toString())
},
onCancel: () => {
console.info("DatePickerDialog:onCancel()")
},
onDateChange: (value: Date) => {
console.info("DatePickerDialog:onDateChange()" + value.toString())
}
})
}
})
.width('100%')
.height(18)
}
}
效果如下:
你还有更好的自定义组件方法?可以互相学习一下…