提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 一、关于样式
- 1 . 默认单位 vp
- 2 . 写公共样式
- 二 、 加载图片
- 三 、 父子组件传值
- 四 、 自定义构建函数 @Builder
- 五、构建函数-@BuilderParam 传递UI
一、关于样式
1 . 默认单位 vp
答: vp 是 virtual pixel 的缩写,根据设备像素密度转化为屏幕物理像素,px 直接表示设备的像素,因为我们设备的分辨率密度不同,最好是使用 vp
适配: 可以使用伸缩布局layoutWeight,flex布局,网格系统,栅格系统布局,
2 . 写公共样式
在开发过程中会出现大量代码在进行重复样式设置,@Styles 和 Extend 可以帮我们进行样式复用
1. @styles 方式
- 只支持通用属性 和 通用事件,且不支持箭头函数语法
- 在组件内(局部)无需加 function , 在组件外(全局) 定义时要加function
@Styles function textStyle () {.width(100).height(50).backgroundColor(Color.Pink).borderRadius(25).onClick(() => {promptAction.showToast({message: "测试"})})
}
2. Extend 方式
- 使用 @Extend 装饰器修饰的函数只能是 全局
- 且参数可以是一个函数,实现复用事件且可处理不同逻辑
- 函数可以进行 传参,如果参数是状态变量,状态更新后会刷新UI
// 全局 原生组件 参数
// ↓ ↓ ↓
@Extend(Text) function textInputAll (callback?: () => void) {.width(100).height(50).backgroundColor(Color.Pink).borderRadius(25).textAlign(TextAlign.Center).fontColor(Color.White).onClick(() => {callback && callback()})
}
二 、 加载图片
- 使用本地图片
// 可以新建一个文件夹,里面放本地图片(ets下)
Image('/assets/a.png')
- 使用 resource 下的 media 图片
// resource/media (a 是文件名,扩展名省略)
Image($r('/app.media.a'))
- 使用 resource 下的 rawfile 图片
// resource/rawfile
Image($rawfile('a.png'))
- 使用网络图片(必须申请网络权限)
// resource/rawfile
Image("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F2bf1b169-d217-44c3-a5b3-dd00813bc20d%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1704614176&t=e15a2fd5193aeeb24fc95b5dbe395907")
"requestPermissions": [{"name":"ohos.permission.INTERNET"
}],
三 、 父子组件传值
- 父传子
// 父组件的子组件上,传递一个对象(HmCommentItem)HmCommentItem({ item:item})
// 子组件上进行接收item: Partial<ReplyItem> = {} // 默认是public
- 子传父(目的是修改父组件的值)
// 父组件的子组件上,传递一个方法(HmCommentItem)HmCommentItem({ item:item,changeLike:(item)=>{this.changeLike(item)}})
// 子组件上进行接收
changeLike: (params: ReplyItem) => void = () => {} // 接受一个无返回值的方法,默认是空函数
四 、 自定义构建函数 @Builder
如果你不想在直接抽象组件, ArkUI 还提供了一种更轻量的UI元素复用机制
@Builder
,可以将重复使用的 UI 元素抽象成一个方法,在 build 方法里调用。称之为自定义构建函数
- 使用@Builder 定义一个函数(全局加function)
- 在组件里使用这个函数
// 定义 Builder
@Builder
function getCellContent(leftTitle: string, rightValue: string) {Row() {Row() {Text(leftTitle)Text(rightValue)}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding({left: 15,right: 15}).borderRadius(8).height(40).backgroundColor(Color.White)}.padding({left: 10,right: 10})}
class CardClass {time: string = ""location: string = ""type: string = ""
}
@State formData: CardClass = {time: "2023-12-12",location: '回龙观',type: '漏油'}
// 在组件里使用
Column({ space: 10 }) {getCellContent("异常时间", this.formData.time)getCellContent("异常位置", this.formData.location)getCellContent("异常类型", this.formData.type)Button("修改数据").onClick(() => {this.formData.location = "望京"})}.width('100%')
全局自定义函数的问题
-
全局的自定义构建函数可以被整个应用获取(下一代可用-当前4.0暂不支持),不允许使用this和bind方法。
-
不可被其他文件引用
-
当我点击按钮时数据即使是响应式的,当数据发生改变,该函数不会自动渲染
- 因为我们刚刚传过去的是一个string类型, string 类型是一个基础类型,按值传递,不具备响应式更新的特点
解决方案:改为按引用传递
- 因为我们刚刚传过去的是一个string类型, string 类型是一个基础类型,按值传递,不具备响应式更新的特点
// 完整代码
@Entry
@Component
struct BuilderCase {@State formData: CardClass = {time: "2023-12-12",location: '回龙观',type: '漏油'}@BuildergetCellContent($$: CellParams) {Row() {Row() {Text($$.leftTitle)Text($$.rightValue)}.width('100%').justifyContent(FlexAlign.SpaceBetween).padding({left: 15,right: 15}).borderRadius(8).height(40).backgroundColor(Color.White)}.padding({left: 10,right: 10})}build() {Row() {Column() {Column({ space: 10 }) {this.getCellContent({ leftTitle: '异常时间', rightValue: this.formData.time })this.getCellContent({ leftTitle: '异常位置', rightValue: this.formData.location })this.getCellContent({ leftTitle: '异常类型', rightValue: this.formData.type })}.width('100%')Button("修改数据").onClick(() => {this.formData.location = "望京"})}.width('100%')}.height('100%').backgroundColor('#ccc')}
}class CardClass {time: string = ""location: string = ""type: string = ""
}
class CellParams {leftTitle: string = ""rightValue: string = ""
}
五、构建函数-@BuilderParam 传递UI
Vue里面有个叫做slot插槽的东西,就是可以传入自定义的结构,整体复用父组件的外观
ArkTS提供了一个叫做BuilderParam的修饰符,你可以在组件中定义这样一个函数属性,在使用组件时直接传入
- 使用@BuilderParam 声明一个组件,子组件要在想要显示插槽的地方来调用传入的方法
- 在父组件里调用并传入,父组件传递是一个函数,这个函数也要使用 @Builder 修饰
// 使用BuilderParam 声明组件
@Component
struct HMCard {@BuilderParamcontent: () => voidbuild() {Column () {Text("卡片组件")Divider()Text("传入内容")if(this.content) {this.content() // 子组件要在想要显示插槽的地方来调用传入的方法}}}
}
@Entry
@Component
struct BuilderParamCase {
// 声明渲染的函数组件@BuildergetContent () {Row() {Text("插槽内容").fontColor(Color.Red)}}build() {Row() {Column() {HMCard({ content: this.getContent }) // 调用组件并传入要渲染的函数}.width('100%')}.height('100%')}
}