Flutter响应式表格插件responsive_table的使用

发布于 1周前 作者 caililin 来自 Flutter

Flutter响应式表格插件responsive_table的使用

示例代码

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:responsive_table/responsive_table.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      initialRoute: '/',
      routes: {
        '/': (_) => DataPage(),
      },
    );
  }
}

class DataPage extends StatefulWidget {
  DataPage({Key? key}) : super(key: key);
  [@override](/user/override)
  _DataPageState createState() => _DataPageState();
}

class _DataPageState extends State<DataPage> {
  late List<DatatableHeader> _headers;

  List<int> _perPages = [10, 20, 50, 100];
  int _total = 100;
  int? _currentPerPage = 10;
  List<bool>? _expanded;
  String? _searchKey = "id";

  int _currentPage = 1;
  bool _isSearch = false;
  List<Map<String, dynamic>> _sourceOriginal = [];
  List<Map<String, dynamic>> _sourceFiltered = [];
  List<Map<String, dynamic>> _source = [];
  List<Map<String, dynamic>> _selecteds = [];
  // ignore: unused_field
  String _selectableKey = "id";

  String? _sortColumn;
  bool _sortAscending = true;
  bool _isLoading = true;
  bool _showSelect = true;
  var random = new Random();

  List<Map<String, dynamic>> _generateData({int n: 100}) {
    final List source = List.filled(n, Random.secure());
    List<Map<String, dynamic>> temps = [];
    var i = 1;
    print(i);
    // ignore: unused_local_variable
    for (var data in source) {
      temps.add({
        "id": i,
        "sku": "$i\000$i",
        "name": "Product $i",
        "category": "Category-$i",
        "price": i * 10.00,
        "cost": "20.00",
        "margin": "${i}0.20",
        "in_stock": "${i}0",
        "alert": "5",
        "received": [i + 20, 150]
      });
      i++;
    }
    return temps;
  }

  _initializeData() async {
    _mockPullData();
  }

  _mockPullData() async {
    _expanded = List.generate(_currentPerPage!, (index) => false);

    setState(() => _isLoading = true);
    Future.delayed(Duration(seconds: 3)).then((value) {
      _sourceOriginal.clear();
      _sourceOriginal.addAll(_generateData(n: random.nextInt(10000)));
      _sourceFiltered = _sourceOriginal;
      _total = _sourceFiltered.length;
      _source = _sourceFiltered.getRange(0, _currentPerPage!).toList();
      setState(() => _isLoading = false);
    });
  }

  _resetData({start: 0}) async {
    setState(() => _isLoading = true);
    var _expandedLen =
        _total - start < _currentPerPage! ? _total - start : _currentPerPage;
    Future.delayed(Duration(seconds: 0)).then((value) {
      _expanded = List.generate(_expandedLen as int, (index) => false);
      _source.clear();
      _source = _sourceFiltered.getRange(start, start + _expandedLen).toList();
      setState(() => _isLoading = false);
    });
  }

  _filterData(value) {
    setState(() => _isLoading = true);

    try {
      if (value == "" || value == null) {
        _sourceFiltered = _sourceOriginal;
      } else {
        _sourceFiltered = _sourceOriginal
            .where((data) => data[_searchKey!]
                .toString()
                .toLowerCase()
                .contains(value.toString().toLowerCase()))
            .toList();
      }

      _total = _sourceFiltered.length;
      var _rangeTop = _total < _currentPerPage! ? _total : _currentPerPage!;
      _expanded = List.generate(_rangeTop, (index) => false);
      _source = _sourceFiltered.getRange(0, _rangeTop).toList();
    } catch (e) {
      print(e);
    }
    setState(() => _isLoading = false);
  }

  [@override](/user/override)
  void initState() {
    super.initState();

    /// 设置表头
    _headers = [
      DatatableHeader(
          text: "ID",
          value: "id",
          show: true,
          sortable: true,
          textAlign: TextAlign.center),
      DatatableHeader(
          text: "Name",
          value: "name",
          show: true,
          flex: 2,
          sortable: true,
          editable: true,
          textAlign: TextAlign.left),
      DatatableHeader(
          text: "SKU",
          value: "sku",
          show: true,
          sortable: true,
          textAlign: TextAlign.center),
      DatatableHeader(
          text: "Category",
          value: "category",
          show: true,
          sortable: true,
          textAlign: TextAlign.left),
      DatatableHeader(
          text: "Price",
          value: "price",
          show: true,
          sortable: true,
          textAlign: TextAlign.left),
      DatatableHeader(
          text: "Margin",
          value: "margin",
          show: true,
          sortable: true,
          textAlign: TextAlign.left),
      DatatableHeader(
          text: "In Stock",
          value: "in_stock",
          show: true,
          sortable: true,
          textAlign: TextAlign.left),
      DatatableHeader(
          text: "Alert",
          value: "alert",
          show: true,
          sortable: true,
          textAlign: TextAlign.left),
      DatatableHeader(
          text: "Received",
          value: "received",
          show: true,
          sortable: false,
          sourceBuilder: (value, row) {
            List list = List.from(value);
            return Container(
              child: Column(
                children: [
                  Container(
                    width: 85,
                    child: LinearProgressIndicator(
                      value: list.first / list.last,
                    ),
                  ),
                  Text("${list.first} of ${list.last}")
                ],
              ),
            );
          },
          textAlign: TextAlign.center),
    ];

    _initializeData();
  }

  [@override](/user/override)
  void dispose() {
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("RESPONSIVE DATA TABLE"),
        actions: [
          IconButton(
            onPressed: _initializeData,
            icon: Icon(Icons.refresh_sharp),
          ),
        ],
      ),
      drawer: Drawer(
        child: ListView(
          children: [
            ListTile(
              leading: Icon(Icons.home),
              title: Text("home"),
              onTap: () {},
            ),
            ListTile(
              leading: Icon(Icons.storage),
              title: Text("data"),
              onTap: () {},
            )
          ],
        ),
      ),
      body: SingleChildScrollView(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              mainAxisSize: MainAxisSize.max,
              children: [
            Container(
              margin: EdgeInsets.all(10),
              padding: EdgeInsets.all(0),
              constraints: BoxConstraints(
                maxHeight: 700,
              ),
              child: Card(
                elevation: 1,
                shadowColor: Colors.black,
                clipBehavior: Clip.none,
                child: ResponsiveDatatable(
                  title: TextButton.icon(
                    onPressed: () {},
                    icon: Icon(Icons.add),
                    label: Text("new item"),
                  ),
                  reponseScreenSizes: [ScreenSize.xs],
                  actions: [
                    if (_isSearch)
                      Expanded(
                          child: TextField(
                        decoration: InputDecoration(
                            hintText: 'Enter search term based on ' +
                                _searchKey!
                                    .replaceAll(new RegExp('[\\W_]+'), ' ')
                                    .toUpperCase(),
                            prefixIcon: IconButton(
                                icon: Icon(Icons.cancel),
                                onPressed: () {
                                  setState(() {
                                    _isSearch = false;
                                  });
                                  _initializeData();
                                }),
                            suffixIcon: IconButton(
                                icon: Icon(Icons.search), onPressed: () {})),
                        onSubmitted: (value) {
                          _filterData(value);
                        },
                      )),
                    if (!_isSearch)
                      IconButton(
                          icon: Icon(Icons.search),
                          onPressed: () {
                            setState(() {
                              _isSearch = true;
                            });
                          })
                  ],
                  headers: _headers,
                  source: _source,
                  selecteds: _selecteds,
                  showSelect: _showSelect,
                  autoHeight: false,
                  dropContainer: (data) {
                    if (int.tryParse(data['id'].toString())!.isEven) {
                      return Text("is Even");
                    }
                    return _DropDownContainer(data: data);
                  },
                  onChangedRow: (value, header) {
                    /// print(value);
                    /// print(header);
                  },
                  onSubmittedRow: (value, header) {
                    /// print(value);
                    /// print(header);
                  },
                  onTabRow: (data) {
                    print(data);
                  },
                  onSort: (value) {
                    setState(() => _isLoading = true);

                    setState(() {
                      _sortColumn = value;
                      _sortAscending = !_sortAscending;
                      if (_sortAscending) {
                        _sourceFiltered.sort((a, b) =>
                            b["$_sortColumn"].compareTo(a["$_sortColumn"]));
                      } else {
                        _sourceFiltered.sort((a, b) =>
                            a["$_sortColumn"].compareTo(b["$_sortColumn"]));
                      }
                      var _rangeTop = _currentPerPage! < _sourceFiltered.length
                          ? _currentPerPage!
                          : _sourceFiltered.length;
                      _source = _sourceFiltered.getRange(0, _rangeTop).toList();
                      _searchKey = value;

                      _isLoading = false;
                    });
                  },
                  expanded: _expanded,
                  sortAscending: _sortAscending,
                  sortColumn: _sortColumn,
                  isLoading: _isLoading,
                  onSelect: (value, item) {
                    print("$value  $item ");
                    if (value!) {
                      setState(() => _selecteds.add(item));
                    } else {
                      setState(
                          () => _selecteds.removeAt(_selecteds.indexOf(item)));
                    }
                  },
                  onSelectAll: (value) {
                    if (value!) {
                      setState(() => _selecteds =
                          _source.map((entry) => entry).toList().cast());
                    } else {
                      setState(() => _selecteds.clear());
                    }
                  },
                  footers: [
                    Container(
                      padding: EdgeInsets.symmetric(horizontal: 15),
                      child: Text("Rows per page:"),
                    ),
                    if (_perPages.isNotEmpty)
                      Container(
                        padding: EdgeInsets.symmetric(horizontal: 15),
                        child: DropdownButton<int>(
                          value: _currentPerPage,
                          items: _perPages
                              .map((e) => DropdownMenuItem<int>(
                                    child: Text("$e"),
                                    value: e,
                                  ))
                              .toList(),
                          onChanged: (dynamic value) {
                            setState(() {
                              _currentPerPage = value;
                              _currentPage = 1;
                              _resetData();
                            });
                          },
                          isExpanded: false,
                        ),
                      ),
                    Container(
                      padding: EdgeInsets.symmetric(horizontal: 15),
                      child:
                          Text("$_currentPage - $_currentPerPage of $_total"),
                    ),
                    IconButton(
                      icon: Icon(
                        Icons.arrow_back_ios,
                        size: 16,
                      ),
                      onPressed: _currentPage == 1
                          ? null
                          : () {
                              var _nextSet = _currentPage - _currentPerPage!;
                              setState(() {
                                _currentPage = _nextSet > 1 ? _nextSet : 1;
                                _resetData(start: _currentPage - 1);
                              });
                            },
                      padding: EdgeInsets.symmetric(horizontal: 15),
                    ),
                    IconButton(
                      icon: Icon(Icons.arrow_forward_ios, size: 16),
                      onPressed: _currentPage + _currentPerPage! - 1 > _total
                          ? null
                          : () {
                              var _nextSet = _currentPage + _currentPerPage!;

                              setState(() {
                                _currentPage = _nextSet < _total
                                    ? _nextSet
                                    : _total - _currentPerPage!;
                                _resetData(start: _nextSet - 1);
                              });
                            },
                      padding: EdgeInsets.symmetric(horizontal: 15),
                    )
                  ],
                  headerDecoration: BoxDecoration(
                      color: Colors.grey,
                      border: Border(
                          bottom: BorderSide(color: Colors.red, width: 1))),
                  selectedDecoration: BoxDecoration(
                    border: Border(
                        bottom:
                            BorderSide(color: Colors.green[300]!, width: 1)),
                    color: Colors.green,
                  ),
                  headerTextStyle: TextStyle(color: Colors.white),
                  rowTextStyle: TextStyle(color: Colors.green),
                  selectedTextStyle: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ])),
    );
  }
}

class _DropDownContainer extends StatelessWidget {
  final Map<String, dynamic> data;
  const _DropDownContainer({Key? key, required this.data}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    List<Widget> _children = data.entries.map<Widget>((entry) {
      Widget w = Row(
        children: [
          Text(entry.key.toString()),
          Spacer(),
          Text(entry.value.toString()),
        ],
      );
      return w;
    }).toList();

    return Container(
      child: Column(
        children: _children,
      ),
    );
  }
}

方法

    onSelect( bool selected, dynamic key);
    onSelectAll( bool selected );
    onTabRow( dynamic row );
    onSort( dynamic value );

属性

    title: Widget
    headers: List<DatatableHeader>
    actions: List<Widget>
    source: List<Map<String, dynamic>>
    selecteds: List<Map<String, dynamic>>
    showSelect: bool
    footers: List<Widget>
    sortColumn: String
    sortAscending: bool
    isLoading: bool,
    autoHeight: bool,

使用说明

本示例展示了如何在 Flutter 应用程序中使用 responsive_table 插件来创建一个响应式的表格。通过此插件,你可以轻松地添加分页、搜索、排序和选择功能。

初始化数据

首先,初始化数据并设置表格头部:

[@override](/user/override)
void initState() {
  super.initState();

  /// 设置表头
  _headers = [
    DatatableHeader(
        text: "ID",
        value: "id",
        show: true,
        sortable: true,
        textAlign: TextAlign.center),
    DatatableHeader(
        text: "Name",
        value: "name",
        show: true,
        flex: 2,
        sortable: true,
        editable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "SKU",
        value: "sku",
        show: true,
        sortable: true,
        textAlign: TextAlign.center),
    DatatableHeader(
        text: "Category",
        value: "category",
        show: true,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "Price",
        value: "price",
        show: true,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "Margin",
        value: "margin",
        show: true,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "In Stock",
        value: "in_stock",
        show: true,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "Alert",
        value: "alert",
        show: true,
        sortable: true,
        textAlign: TextAlign.left),
    DatatableHeader(
        text: "Received",
        value: "received",
        show: true,
        sortable: false,
        sourceBuilder: (value, row) {
          List list = List.from(value);
          return Container(
            child: Column(
              children: [
                Container(
                  width: 85,
                  child: LinearProgressIndicator(
                    value: list.first / list.last,
                  ),
                ),
                Text("${list.first} of ${list.last}")
              ],
            ),
          );
        },
        textAlign: TextAlign.center),
  ];

  _initializeData();
}

构建表格

build 方法中构建表格:

[@override](/user/override)
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("RESPONSIVE DATA TABLE"),
      actions: [
        IconButton(
          onPressed: _initializeData,
          icon: Icon(Icons.refresh_sharp),
        ),
      ],
    ),
    drawer: Drawer(
      child: ListView(
        children: [
          ListTile(
            leading: Icon(Icons.home),
            title: Text("home"),
            onTap: () {},
          ),
          ListTile(
            leading: Icon(Icons.storage),
            title: Text("data"),
            onTap: () {},
          )
        ],
      ),
    ),
    body: SingleChildScrollView(
        child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            mainAxisSize: MainAxisSize.max,
            children: [
      Container(
        margin: EdgeInsets.all(10),
        padding: EdgeInsets.all(0),
        constraints: BoxConstraints(
          maxHeight: 700,
        ),
        child: Card(
          elevation: 1,
          shadowColor: Colors.black,
          clipBehavior: Clip.none,
          child: ResponsiveDatatable(
            title: TextButton.icon(
              onPressed: () {},
              icon: Icon(Icons.add),
              label: Text("new item"),
            ),
            reponseScreenSizes: [ScreenSize.xs],
            actions: [
              if (_isSearch)
                Expanded(
                    child: TextField(
                  decoration: InputDecoration(
                      hintText: 'Enter search term based on ' +
                          _searchKey!
                              .replaceAll(new RegExp('[\\W_]+'), ' ')
                              .toUpperCase(),
                      prefixIcon: IconButton(
                          icon: Icon(Icons.cancel),
                          onPressed: () {
                            setState(() {
                              _isSearch = false;
                            });
                            _initializeData();
                          }),
                      suffixIcon: IconButton(
                          icon: Icon(Icons.search), onPressed: () {})),
                  onSubmitted: (value) {
                    _filterData(value);
                  },
                )),
              if (!_isSearch)
                IconButton(
                    icon: Icon(Icons.search),
                    onPressed: () {
                      setState(() {
                        _isSearch = true;
                      });
                    })
            ],
            headers: _headers,
            source: _source,
            selecteds: _selecteds,
            showSelect: _showSelect,
            autoHeight: false,
            dropContainer: (data) {
              if (int.tryParse(data['id'].toString())!.isEven) {
                return Text("is Even");
              }
              return _DropDownContainer(data: data);
            },
            onChangedRow: (value, header) {
              /// print(value);
              /// print(header);
            },
            onSubmittedRow: (value, header) {
              /// print(value);
              /// print(header);
            },
            onTabRow: (data) {
              print(data);
            },
            onSort: (value) {
              setState(() => _isLoading = true);

              setState(() {
                _sortColumn = value;
                _sortAscending = !_sortAscending;
                if (_sortAscending) {
                  _sourceFiltered.sort((a, b) =>
                      b["$_sortColumn"].compareTo(a["$_sortColumn"]));
                } else {
                  _sourceFiltered.sort((a, b) =>
                      a["$_sortColumn"].compareTo(b["$_sortColumn"]));
                }
                var _rangeTop = _currentPerPage! < _sourceFiltered.length
                    ? _currentPerPage!
                    : _sourceFiltered.length;
                _source = _sourceFiltered.getRange(0, _rangeTop).toList();
                _searchKey = value;

                _isLoading = false;
              });
            },
            expanded: _expanded,
            sortAscending: _sortAscending,
            sortColumn: _sortColumn,
            isLoading: _isLoading,
            onSelect: (value, item) {
              print("$value  $item ");
              if (value!) {
                setState(() => _selecteds.add(item));
              } else {
                setState(
                    () => _selecteds.removeAt(_selecteds.indexOf(item)));
              }
            },
            onSelectAll: (value) {
              if (value!) {
                setState(() => _selecteds =
                    _source.map((entry) => entry).toList().cast());
              } else {
                setState(() => _selecteds.clear());
              }
            },
            footers: [
              Container(
                padding: EdgeInsets.symmetric(horizontal: 15),
                child: Text("Rows per page:"),
              ),
              if (_perPages.isNotEmpty)
                Container(
                  padding: EdgeInsets.symmetric(horizontal: 15),
                  child: DropdownButton<int>(
                    value: _currentPerPage,
                    items: _perPages
                        .map((e) => DropdownMenuItem<int>(
                              child: Text("$e"),
                              value: e,
                            ))
                        .toList(),
                    onChanged: (dynamic value) {
                      setState(() {
                        _currentPerPage = value;
                        _currentPage = 1;
                        _resetData();
                      });
                    },
                    isExpanded: false,
                  ),
                ),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 15),
                child:
                    Text("$_currentPage - $_currentPerPage of $_total"),
              ),
              IconButton(
                icon: Icon(
                  Icons.arrow_back_ios,
                  size: 16,
                ),
                onPressed: _currentPage == 1
                    ? null
                    : () {
                        var _nextSet = _currentPage - _currentPerPage!;
                        setState(() {
                          _currentPage = _nextSet > 1 ? _nextSet : 1;
                          _resetData(start: _currentPage - 1);
                        });
                      },
                padding: EdgeInsets.symmetric(horizontal: 15),
              ),
              IconButton(
                icon: Icon(Icons.arrow_forward_ios, size: 16),
                onPressed: _currentPage + _currentPerPage! - 1 > _total
                    ? null
                    : () {
                        var _nextSet = _currentPage + _currentPerPage!;

                        setState(() {
                          _currentPage = _nextSet < _total
                              ? _nextSet
                              : _total - _currentPerPage!;
                          _resetData(start: _nextSet - 1);
                        });
                      },
                padding: EdgeInsets.symmetric(horizontal: 15),
              )
            ],
            headerDecoration: BoxDecoration(
                color: Colors.grey,
                border: Border(
                    bottom: BorderSide(color: Colors.red, width: 1))),
            selectedDecoration: BoxDecoration(
              border: Border(
                  bottom:
                      BorderSide(color: Colors.green[300]!, width: 1)),
              color: Colors.green,
            ),
            headerTextStyle: TextStyle(color: Colors.white),
            rowTextStyle: TextStyle(color: Colors.green),
            selectedTextStyle: TextStyle(color: Colors.white),
          ),
        ),
      ),
    ])),
);
}

更多关于Flutter响应式表格插件responsive_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter响应式表格插件responsive_table的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter中的responsive_table插件来创建响应式表格的示例代码。responsive_table插件允许你创建在不同屏幕尺寸上都能很好显示的表格。

首先,你需要在pubspec.yaml文件中添加responsive_table依赖:

dependencies:
  flutter:
    sdk: flutter
  responsive_table: ^0.3.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

接下来是一个完整的Flutter应用示例,展示如何使用responsive_table插件:

import 'package:flutter/material.dart';
import 'package:responsive_table/responsive_table.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Responsive Table Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final List<Map<String, String>> data = [
    {"Name": "Alice", "Age": "24", "Country": "USA"},
    {"Name": "Bob", "Age": "30", "Country": "UK"},
    {"Name": "Charlie", "Age": "29", "Country": "Canada"},
    {"Name": "David", "Age": "22", "Country": "Australia"},
  ];

  final List<String> columns = ["Name", "Age", "Country"];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Responsive Table Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: ResponsiveTable(
          columns: columns,
          data: data,
          columnWidths: {
            "Name": FlexibleColumnWidth(flex: 2),
            "Age": FlexibleColumnWidth(flex: 1),
            "Country": FlexibleColumnWidth(flex: 2),
          },
          cellDecorators: {
            "Name": (value) => Text(value, style: TextStyle(fontWeight: FontWeight.bold)),
            "Age": (value) => Text(value, style: TextStyle(color: Colors.red)),
            "Country": (value) => Text(value, style: TextStyle(decoration: TextDecoration.underline)),
          },
          headerStyle: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
          dataRowStyle: TextStyle(fontSize: 18),
        ),
      ),
    );
  }
}

代码解释

  1. 依赖引入:在pubspec.yaml中引入responsive_table插件。

  2. 数据准备:在MyHomePage类中,我们准备了一些示例数据data和一个列名列表columns

  3. ResponsiveTable组件

    • columns:指定表格的列名。
    • data:提供表格的数据。
    • columnWidths:定义每列的宽度,这里使用了FlexibleColumnWidth来根据flex值分配宽度。
    • cellDecorators:允许你对每个单元格的内容进行自定义装饰,例如改变文本样式。
    • headerStyle:定义表头的样式。
    • dataRowStyle:定义数据行的样式。

运行这个示例应用,你将看到一个响应式的表格,它在不同屏幕尺寸上都能很好地显示,并且每列的宽度和内容样式都可以根据需要进行自定义。

希望这个示例能帮助你理解如何使用responsive_table插件来创建响应式表格!

回到顶部