We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
以 ArkUI - 列表布局(List) 那一篇文章的2024春节档电影新片票房榜列表例子为例:
2024春节档电影新片票房榜
@Entry @Component struct Index { ... build() { Column({ space: 8 }) { // 标题部分 Row() { ... } // 电影列表部分 List() { ForEach( ... ) } } } }
这是整体的代码结构,省略了细节部分。整个页面是一个从上到下的列式布局,所以我们使用了 Column 容器。然后页面分成了两部分,第一部分是顶部的标题,第二部分是电影列表,由于每一行的内容基本相似,所以我们使用 ForEach 在内部循环渲染电影对应的卡片。
以上面的标题部分为例,我们知道标题部分其实是一个标准化的功能,也就是说不仅这个页面需要这样的标题,其他页面也需要。比如产品在设计UE时,通常来说会把列表页面和列表详情页的标题部分设置成相似的。如果在每个页面里都写类似的标题代码,复用性会很差,所以为了解决这个问题我们可以把标题部分封装到自定义组件里。
@Component struct Header { build() { // 标题部分 Row() { ... } } }
我们定义了一个结构体 Header,代表页面的头部。然后加上 @Component 装饰器,这样一个组件就声明出来了。紧接着,可以把标题部分的代码抽取到 builde() { } 里,这样一个可复用的标题的功能就封装好了。
Header
@Component
builde() { }
将来在电影列表页面里,我需要写标题,不需要在重新写标题代码了,直接引用这个 Header 组件就行了:
@Entry @Component struct Index { ... build() { Column({ space: 8 }) { // 标题部分 Header() // 电影列表部分 List() { ForEach( ... ) } } } }
定义在页面内部的自定义组件完整代码如下:
@Component struct Header { private title: string build() { Row() { Text(this.title) .fontSize(30) .fontWeight(FontWeight.Bold) } } } @Entry @Component struct Index { ... build() { Column({ space: 8 }) { // 标题部分 Header({ title: '2024春节档新片票房榜' }) .margin({ bottom: 20 }) ... } } }
但是,如果定义在页面内部,也就意味着只有在这个页面能用,换一个页面就用不了了。所以最佳的方案时定义在单独的文件里。
在 entry 的 ets 文件夹里新建 components 文件夹,并在里面新建一个 CommonComponents.ets 文件。将上面 Header 代码拷贝到这个文件里,为了能让别的文件使用这段代码,需要做一些修改:
@Component export struct Header { build() { Row() { ... } } }
使用 export 将 Header 导出,这样别的文件才能 import 导入使用:
export
import
import { Header } from '../components/CommonComponents'
定义在页面外部的自定义组件完整代码如下:
CommonComponents.ets
@Component export struct Header { private title: string build() { Row() { Text(this.title) .fontSize(30) .fontWeight(FontWeight.Bold) } } }
Index.ets
import { Header } from '../components/CommonComponents' @Entry @Component struct Index { ... build() { Column({ space: 8 }) { // 标题部分 Header({ title: '2024春节档新片票房榜' }) .margin({ bottom: 20 }) ... } } }
@Builder
这是我们的 Index.ets 代码:
... @Entry @Component struct Index { ... build() { Column({ space: 8 }) { ... // 电影列表部分 List({ space: 8 }) { ForEach( this.items, (item: Item) => { ListItem() { Row({ space: 8 }) { Image(item.image) .width(157) .height(220) Column() { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text(item.box_office) .fontSize(18) } .height('100%') .alignItems(HorizontalAlign.Start) } .width('100%') .height(220) } } ) } .width('100%') .height('100%') } .width('100%') .height('100%') .padding(8) } }
从这段代码可以发现,List 里面的代码可读性不高。最好是能把下面这段代码封装起来:
Row({ space: 8 }) { Image(item.image) .width(157) .height(220) Column() { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text(item.box_office) .fontSize(18) } .height('100%') .alignItems(HorizontalAlign.Start) } .width('100%') .height(220)
可以使用自定义组件,也可以使用自定构建函数 @Builder,它用来做这种内部的页面封装会更加合适一些。
自定构建函数顾名思义就是用来构建页面的一个函数,可以把相关代码封装进去:
全局自定义构建函数
代码结构:
@Builder function 函数名() { ... }
完整代码:
... @Builder function ItemCard(item:Item) { Row({ space: 8 }) { Image(item.image) .width(157) .height(220) Column() { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text(item.box_office) .fontSize(18) } .height('100%') .alignItems(HorizontalAlign.Start) } .width('100%') .height(220) } @Entry @Component struct Index { ... build() { Column({ space: 8 }) { ... // 电影列表部分 List({ space: 8 }) { ForEach( this.items, (item: Item) => { ListItem() { ItemCard(item) } } ) } .width('100%') .height('100%') } .width('100%') .height('100%') .padding(8) } }
组件内自定义构建函数
@Builder 函数名() { ... }
... @Entry @Component struct Index { ... build() { Column({ space: 8 }) { ... // 电影列表部分 List({ space: 8 }) { ForEach( this.items, (item: Item) => { ListItem() { this.ItemCard(item) } } ) } .width('100%') .height('100%') } .width('100%') .height('100%') .padding(8) } @Builder ItemCard(item: Item) { Row({ space: 8 }) { Image(item.image) .width(157) .height(220) Column() { Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold) Text(item.box_office) .fontSize(18) } .height('100%') .alignItems(HorizontalAlign.Start) } .width('100%') .height(220) } }
@Styles
@Entry @Component struct Index { ... build() { Column() { ... } .width('100%') .height('100%') .padding(8) } ... }
如上代码所示,是一个 Column 容器,这个 Column 是有很多样式的,比如这里的宽100%、高100%等,这种样式可以认为是 App 的统一样式,也就是通用样式,如果每个页面都去写这些代码是不是也是浪费,这种也可以做抽取,这是对样式的抽取,就要用到 @Styles 装饰器。
全局公共样式
@Styles function 函数名() { ... }
@Styles function fillScreen() { .width('100%') .height('100%') .padding(8) } @Entry @Component struct Index { ... build() { Column() { ... } .fillScreen() } ... }
内部共样式
@Styles 函数名() { ... }
@Entry @Component struct Index { @Styles function fillScreen() { .width('100%') .height('100%') .padding(8) } ... build() { Column() { ... } .fillScreen() } ... }
@Extend
Text(item.name) .fontSize(20) .fontWeight(FontWeight.Bold)
如上代码所示,fontSize 和 fontWeight 是 Text 组件的特有属性,如果页面中有相同的代码,可以使用 @Extend 抽取。
@Extend(组件) function 函数名() { ... }
@Extend(Text) function nameText() { .fontSize(20) .fontWeight(FontWeight.Bold) } Text(item.name) .nameText()
切记 @Extend 不能写在组件内,只能写在全局。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
以 ArkUI - 列表布局(List) 那一篇文章的
2024春节档电影新片票房榜
列表例子为例:这是整体的代码结构,省略了细节部分。整个页面是一个从上到下的列式布局,所以我们使用了 Column 容器。然后页面分成了两部分,第一部分是顶部的标题,第二部分是电影列表,由于每一行的内容基本相似,所以我们使用 ForEach 在内部循环渲染电影对应的卡片。
一、创建自定义组件
以上面的标题部分为例,我们知道标题部分其实是一个标准化的功能,也就是说不仅这个页面需要这样的标题,其他页面也需要。比如产品在设计UE时,通常来说会把列表页面和列表详情页的标题部分设置成相似的。如果在每个页面里都写类似的标题代码,复用性会很差,所以为了解决这个问题我们可以把标题部分封装到自定义组件里。
我们定义了一个结构体
Header
,代表页面的头部。然后加上@Component
装饰器,这样一个组件就声明出来了。紧接着,可以把标题部分的代码抽取到builde() { }
里,这样一个可复用的标题的功能就封装好了。将来在电影列表页面里,我需要写标题,不需要在重新写标题代码了,直接引用这个 Header 组件就行了:
定义在页面内部的自定义组件完整代码如下:
但是,如果定义在页面内部,也就意味着只有在这个页面能用,换一个页面就用不了了。所以最佳的方案时定义在单独的文件里。
在 entry 的 ets 文件夹里新建 components 文件夹,并在里面新建一个 CommonComponents.ets 文件。将上面 Header 代码拷贝到这个文件里,为了能让别的文件使用这段代码,需要做一些修改:
使用
export
将 Header 导出,这样别的文件才能import
导入使用:定义在页面外部的自定义组件完整代码如下:
CommonComponents.ets
Index.ets
二、自定义构建函数
@Builder
这是我们的 Index.ets 代码:
从这段代码可以发现,List 里面的代码可读性不高。最好是能把下面这段代码封装起来:
可以使用自定义组件,也可以使用自定构建函数
@Builder
,它用来做这种内部的页面封装会更加合适一些。自定构建函数顾名思义就是用来构建页面的一个函数,可以把相关代码封装进去:
全局自定义构建函数
代码结构:
完整代码:
组件内自定义构建函数
代码结构:
完整代码:
三、自定义公共样式
@Styles
如上代码所示,是一个 Column 容器,这个 Column 是有很多样式的,比如这里的宽100%、高100%等,这种样式可以认为是 App 的统一样式,也就是通用样式,如果每个页面都去写这些代码是不是也是浪费,这种也可以做抽取,这是对样式的抽取,就要用到
@Styles
装饰器。全局公共样式
代码结构:
完整代码:
内部共样式
代码结构:
完整代码:
四、自定义组件特有属性
@Extend
如上代码所示,fontSize 和 fontWeight 是 Text 组件的特有属性,如果页面中有相同的代码,可以使用
@Extend
抽取。代码结构:
完整代码:
切记
@Extend
不能写在组件内,只能写在全局。The text was updated successfully, but these errors were encountered: