HarmonyOS鸿蒙Next开发有没有Table组件?

HarmonyOS鸿蒙Next开发有没有Table组件? 大神们好!请问一下,鸿蒙开发有没有Table组件?如何使用?

8 回复

手搓好的组件案例,拿去

interface TableColumn {
  key: string;
  title: string;
  flex: number;
  align: TextAlign;
}

interface TableRow {
  name: string;
  age: number;
  city: string;
  job: string;
}

@Entry
@ComponentV2
struct Table {
  private readonly horizontalGap: number = 8;
  private readonly verticalGap: number = 6;
  @Local columns: TableColumn[] = [
    {
      key: 'name',
      title: '姓名',
      flex: 2,
      align: TextAlign.Start
    },
    {
      key: 'age',
      title: '年龄',
      flex: 1,
      align: TextAlign.Center
    },
    {
      key: 'city',
      title: '城市',
      flex: 2,
      align: TextAlign.Start
    },
    {
      key: 'job',
      title: '职位',
      flex: 2,
      align: TextAlign.Start
    }
  ];
  @Local rows: TableRow[] = [
    {
      name: '张三',
      age: 28,
      city: '深圳',
      job: '开发工程师'
    },
    {
      name: '李四',
      age: 32,
      city: '上海',
      job: '产品经理'
    },
    {
      name: '王五',
      age: 26,
      city: '北京',
      job: '测试工程师'
    },
    {
      name: '赵六',
      age: 30,
      city: '广州',
      job: '设计师'
    },
    {
      name: '周七',
      age: 35,
      city: '杭州',
      job: '架构师'
    }
  ];

  build(): void {
    Column({ space: this.verticalGap }) {
      this.renderHeader();
      List({ space: this.verticalGap }) {
        ForEach(this.rows, (row: TableRow, index: number) => {
          ListItem() {
            this.renderRow(row, index);
          }
          .padding({
            top: 10,
            bottom: 10,
            left: 12,
            right: 12
          })
          .backgroundColor(index % 2 === 0 ? '#F7F8FA' : Color.White);
        }, (row: TableRow, index: number) => `${row.name}-${index}`);
      }
      .cachedCount(5)
      .edgeEffect(EdgeEffect.Spring)
      .height('80%');
    }
    .padding(16)
    .backgroundColor(Color.White);
  }

  /**
   * 渲染表头。
   */
  @Builder
  renderHeader(): void {
    Row({ space: this.horizontalGap }) {
      ForEach(this.columns, (column: TableColumn) => {
        Row() {
          Text(column.title)
            .fontWeight(FontWeight.Medium)
            .fontColor(Color.White)
            .textAlign(column.align);
        }
        .layoutWeight(column.flex)
        .justifyContent(this.getCellAlign(column.align))
        .height(36);
      }, (column: TableColumn) => column.key);
    }
    .padding({ left: 12, right: 12 })
    .backgroundColor('#3451F1')
    .borderRadius(10);
  }

  /**
   * 渲染单行数据。
   */
  @Builder
  renderRow(row: TableRow, index: number): void {
    Row({ space: this.horizontalGap }) {
      ForEach(this.columns, (column: TableColumn) => {
        Row() {
          Text(this.getCellContent(row, column.key))
            .fontColor(Color.Black)
            .textAlign(column.align)
            .maxLines(1)
            .textOverflow({ overflow: TextOverflow.Ellipsis });
        }
        .layoutWeight(column.flex)
        .justifyContent(this.getCellAlign(column.align));
      }, (column: TableColumn) => `${column.key}-${index}`);
    }
  }

  /**
   * 根据表头配置返回对应的单元格文本。
   */
  private getCellContent(row: TableRow, key: string): string {
    let value: string = '';
    switch (key) {
      case 'name':
        value = row.name;
        break;
      case 'age':
        value = `${row.age}`;
        break;
      case 'city':
        value = row.city;
        break;
      case 'job':
        value = row.job;
        break;
      default:
        value = '';
        break;
    }
    return value;
  }

  /**
   * 将文本对齐方式映射到 Flex 对齐。
   */
  private getCellAlign(align: TextAlign): FlexAlign {
    let cellAlign: FlexAlign = FlexAlign.Start;
    switch (align) {
      case TextAlign.Start:
        cellAlign = FlexAlign.Start;
        break;
      case TextAlign.Center:
        cellAlign = FlexAlign.Center;
        break;
      case TextAlign.End:
        cellAlign = FlexAlign.End;
        break;
      default:
        cellAlign = FlexAlign.Start;
        break;
    }
    return cellAlign;
  }
}

更多关于HarmonyOS鸿蒙Next开发有没有Table组件?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


目前,HarmonyOS 原生框架中没有提供的 Table 表格组件

方案一:使用 Web 组件加载 HTML 表格

通过 Web 组件加载本地或在线的 HTML 文件,在其中使用标准的 <table> 标签实现表格功能。这种方式适合需要复杂表格样式和交互的场景。

示例代码:

Web({ src: $rawfile('table.html'), controller: this.controller })
  .width('100%')
  .height('100%')

HTML 文件(resources/rawfile/table.html)中写标准的 <table> 结构即可。

方案二:使用三方表格组件

社区已有开发者封装了鸿蒙可用的表格组件,以下是两个较受欢迎的三方库:

  1. @wgw/table

    • 支持基本表格布局
    • 支持固定行列、拖拽调整宽高
    • 适合轻量级使用
  2. @wuyo/wuyotable

    • 支持多级表头(一级、二级、三级)
    • 支持行列固定
    • 更适合复杂数据展示场景

请使用:列表 (List) 组件

列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等)。

使用列表可以轻松高效地显示结构化、可滚动的信息。通过在List组件中按垂直或者水平方向线性排列子组件ListItemGroupListItem,为列表中的行或列提供单个视图,或使用循环渲染迭代一组行或列,或混合任意数量的单个视图和ForEach结构,构建一个列表。List组件支持使用条件渲染、循环渲染、懒加载渲染控制方式生成子组件。

在圆形屏幕设备上,推荐使用ArcList组件,使用方式可参考创建弧形列表 (ArcList)

列表作为一种容器,会自动按其滚动方向排列子组件,向列表中添加组件或从列表中移除组件会重新排列子组件。

如下图所示,在垂直列表中,List按垂直方向自动排列ListItemGroup或ListItem。

ListItemGroup用于列表数据的分组展示,其子组件也是ListItem。ListItem表示单个列表项,可以包含单个子组件。

List、ListItemGroup和ListItem组件关系:

cke_1252.png

Demo:

@State messages: Message[] = [
    { id: 1, content: '欢迎~~', sender: '系统' },
    { id: 2, content: '大家好啊~', sender: '主播' }
];
build() {
  Column() {
    List({ space: 10 }) {
      ForEach(this.messages, (item: Message) => {
        ListItem() {
          this.MessageItem(item)
        }
      }, (item: Message) => item.id.toString())
    }
    .stackFromEnd(true)
    .layoutWeight(1)
    .alignListItem(ListItemAlign.Center)
    // ...
  }
  .width('100%')
  .height('100%')
}

你好,HarmonyOS目前没有表格组件,暂时只能使用web组件引入一个本地的html,在html中绘制一个表格。demo如下:

import web_webview from '@ohos.web.webview'

@Entry
@Component

struct TableHtml {
  controller: web_webview.WebviewController = new web_webview.WebviewController();
  build() {
    Column() {
      Button("点击此处,加载HTML富文本").onClick(() => {
        this.controller.loadData(`<html> <head> <style> .table-font-size{ font-size:20px; } </style> </head> <body bgcolor=\"white\"> <table width="1000" border="5" height="1000"> <tr class="table-font-size"> <th>Month</th> <th>Month</th> </tr> <tr class="table-font-size"> <th>Month</th> <th>Month</th> </tr> <tr class="table-font-size"> <th>Month</th> <th>Month</th> </tr> <tr class="table-font-size"> <th>Month</th> <th>Month</th> </tr> </table> </body></html>`, "text/html", "UTF-8");
      }) // 通过$rawfile加载本地资源文件。
      Web({ src: 'www', controller: this.controller }).javaScriptAccess(true).domStorageAccess(true).fileAccess(true)
      // .defaultFontSize(this.fontSize)
    }
  }
}

或者使用,使用Scroll嵌套List实现可滚动表格

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

有没有可能他不叫table叫list,

HarmonyOS Next Table组件

HarmonyOS Next提供Table组件,位于ArkUI框架中。该组件支持多行多列数据展示,具备固定表头、列宽调整和滚动功能。开发者可通过Table、TableColumn、TableCell等子组件构建表格,并绑定数据源实现动态渲染。

在HarmonyOS Next(API 11)中,目前没有直接命名为“Table”的独立组件。

但是,您可以通过组合使用多个基础组件来构建表格布局,实现类似Table的功能。最核心和推荐的方式是使用 <Grid> 网格容器组件

实现方案:

  1. 核心组件:<Grid> 这是构建表格布局的首选。您可以将其columnsTemplate属性设置为类似'1fr 1fr 1fr'来定义列数和比例(例如等宽三列),然后在其中按行顺序排列子组件。每个子组件占据一个网格单元格。

    • 优点:布局能力强,易于实现规整的行列对齐。
    • 示例:一个简单的3列数据展示。
      Grid() {
        Text('姓名').width('100%').height(50) // 第1行第1列
        Text('年龄').width('100%').height(50) // 第1行第2列
        Text('城市').width('100%').height(50) // 第1行第3列
      
        Text('张三').width('100%').height(40) // 第2行第1列
        Text('25').width('100%').height(40)   // 第2行第2列
        Text('北京').width('100%').height(40) // 第2行第3列
        // ... 更多数据行
      }
      .columnsTemplate('1fr 1fr 1fr') // 定义等宽三列
      .rowsTemplate('50 40 40') // 可定义行高,此处示例
      
  2. 列表渲染:结合ForEach 对于动态数据,使用GridFlex配合ForEach进行循环渲染,是构建数据表格的标准做法。

    • 示例
      @State data: Person[] = [...]; // 您的数据数组
      
      Grid() {
        // 表头
        Text('姓名').width('100%')
        Text('年龄').width('100%')
        Text('城市').width('100%')
      
        // 数据行
        ForEach(this.data, (item: Person) => {
          Text(item.name).width('100%')
          Text(item.age.toString()).width('100%')
          Text(item.city).width('100%')
        })
      }
      .columnsTemplate('1fr 1fr 1fr')
      
  3. 替代方案:<Flex><Row> + <Column>

    • <Flex>: 通过Flex({ direction: FlexDirection.Column })创建列,内部每个子项用Flex({ direction: FlexDirection.Row })创建行,再在行内放置单元格数据。这种方式在布局上更灵活,但需要手动控制对齐。
    • <Row><Column>: 可以进行嵌套来实现,但代码结构可能比Grid更复杂。

总结: 虽然没有现成的、封装好的<Table>组件,但使用**<Grid>组件**并定义其columnsTemplate,是构建具有固定列结构的表格视图最清晰、高效的方式。对于复杂的交互表格(如排序、过滤),您需要在此布局基础上,自行实现表头交互和状态管理逻辑。

回到顶部