一、关于样式
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
- 使用@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: '漏油'
}
@Builder
getCellContent($$: 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
- 使用@BuilderParam 声明一个组件,子组件要在想要显示插槽的地方来调用传入的方法
- 在父组件里调用并传入,父组件传递是一个函数,这个函数也要使用 @Builder 修饰
// 使用BuilderParam 声明组件
@Component
struct HMCard {
@BuilderParam
content: () => void
build() {
Column () {
Text("卡片组件")
Divider()
Text("传入内容")
if(this.content) {
this.content() // 子组件要在想要显示插槽的地方来调用传入的方法
}
}
}
}
@Entry
@Component
struct BuilderParamCase {
// 声明渲染的函数组件
@Builder
getContent () {
Row() {
Text("插槽内容")
.fontColor(Color.Red)
}
}
build() {
Row() {
Column() {
HMCard({ content: this.getContent }) // 调用组件并传入要渲染的函数
}
.width('100%')
}
.height('100%')
}
}