本文完整版:《在 Vue3 + Element Plus 中生成动静表格,动静批改表格,多级表头,合并单元格》
在 Vue 中,表格组件是应用频率及复杂度排名第一的组件,前端常常须要依据后盾返回的数据动静渲染表格,比方动静表格如何生成,因为表格的列并不是固定的,在未知表格具体有哪些列的场景下,前端如何动静渲染表格数据。又或者须要把表格单元格进行合并解决,比方第一列是日期,须要把雷同的日期进行合并,这样表格看起来会更加清晰。 本文手把手教你如何在 Vue3 + Element Plus 中创建表格、生成动静表格、创立动静多级表头、表格行合并、列合并等问题。
如果你正在搭建后盾管理工具,又不想解决前端问题,举荐应用卡拉云 ,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即可疾速搭建属于你本人的后盾管理工具,一周工作量缩减至一天,详见本文文末。
通过本文你能够学到
- 如何在 Element Plus 中生成动静表格
- 如何在 Element Plus 中动静批改表格
- 如何在 Element Plus 中创立动静多级表头
先来展现个「动静批改表格」的最终效果图吧
Vue3 + Element Plus 配置环境
先应用 vue-cli 初始化利用,这里咱们抉择 vue3 的版本:
vue create kalacloud-vue3-element-plus-table// ORnpx vue create kalacloud-vue3-element-plus-table
而后装置 UI 框架 Element Plus:
npm install element-plus --save// ORyarn add element-plus
装置实现后,在我的项目里导入 ElementPlus,批改 main.js 如下:
import { createApp } from 'vue'import ElementPlus from 'element-plus'import 'element-plus/dist/index.css'import App from './App.vue'const app = createApp(App)app.use(ElementPlus)app.mount('#app')
导入后,就能够启动我的项目了,执行以下命令:
看到以下界面阐明我的项目胜利启动了!前面就能够进入本教程的正式内容了。
Vue3 + Element Plus 生成动静表格
有一个场景是表格列并不是固定的,不能在前端写死,而是须要通过后端返回的数据进行动静渲染,比方后端返回了如下的表头数据:
tableHeader: { name: "姓名", birth: "生日", address: "地址", age: "年龄", phone: "电话",}
这个对象中的 key
对应表格数据中的 prop
,value
对应理论显示的 label
,这样通过一个简略的对象,就能够连贯表头和 表格body
之间的关系。而后还须要后端返回具体的表格数据:
tableData: [{ name: '张三', date: '2016-05-02', address: '上海市普陀区金沙江路 1518 弄', age: 18, phone:"12345678910",}, { date: '2016-05-04', name: '李四', address: '上海市普陀区金沙江路 1517 弄', age: 19, phone:"12345678911",}, { date: '2016-05-01', name: '王五', address: '上海市普陀区金沙江路 1519 弄', age: 20, phone:"12345678912",}, { date: '2016-05-03', name: '赵六', address: '上海市普陀区金沙江路 1516 弄', age: 21, phone:"12345678913",}]
实现表格列动静渲染的性能,须要用到一个很要害的 vue
指令,那就是 v-for
,v-for
不仅能够遍历数据,也能够遍历对象:
<div v-for="(value, key) in object"> {{ key }}: {{ value }}</div>
这里咱们就须要用到这个个性,来对 tableHeader
进行遍历,获取 key
和 value
。基于以上解说,当初咱们具体实际一下如何实现表格列的动静渲染。在 components
目录中新建 DynamicTable.vue
:
<template> <div> <h2>Vue3 + Element plus 动静表格</h2> <el-table :data="tableData" style="width: 100%"> <el-table-column :prop="index" :label="item" v-for="(item, index) in tableHeader" :key="index" > </el-table-column> </el-table> </div></template><script>export default { name: "test", data() { return { tableHeader: { name: "姓名", birth: "生日", address: "地址", age: "年龄", phone: "电话", }, tableData: [{ name: '张三', address: '上海市普陀区金沙江路 1518 弄', birth: '2016-05-02', age: 18, phone: "12345678910", }, { name: '李四', birth: '2016-05-04', address: '上海市普陀区金沙江路 1517 弄', age: 19, phone: "12345678911", }, { name: '王五', birth: '2016-05-01', address: '上海市普陀区金沙江路 1519 弄', age: 20, phone: "12345678912", }, { name: '赵六', birth: '2016-05-03', address: '上海市普陀区金沙江路 1516 弄', age: 21, phone: "12345678913", }] } },}</script>
组件编写实现后,批改 App.vue,导入该组件即可:
<template> <DynamicTable /></template><script>import DynamicTable from './components/DynamicTable.vue'export default { name: 'App', components: { DynamicTable }}</script><style>#app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;}</style>
保留后页面会主动热更新,实现成果如下:
这个只是比拟根本的应用,如果某些列有一些定制需要,比方须要反对依据日期排序,这个时候能够对 tableHeader
进行革新,使 value
是一个对象,这样就能够携带更多的表头配置信息:
tableHeader: { name: { label: "姓名", sort: true, }, birth: { label: "生日", sort: false, }, address: { label: "地址", sort: false, }, age: { label: "年龄", sort: true, }, phone: { label: "电话", sort: false, }},
而后再革新 el-table 如下:
<el-table-column :prop="index" :label="item.label" v-for="(item, index) in tableHeader" :sortable="item.sort" :key="index">
以上就实现了基于动静列的表头配置,这里的关键在于 tableHeader
的数据结构如何定义,能够把列信息都放在 tableHeader
中,而后再通过 v-for 循环列就能够渲染出对应的表格列。当然 tableHeader
也能够是一个数组,应用办法都是相似的,大家能够本人去尝试一下。
扩大浏览:《多款好用的 vue 表单设计器举荐测评》
Vue3 + Element Plus 动静批改表格
基于以上的思路,咱们还能够做的更多,比方动静增加指定行,指定列,或者删除指定行或者列等操作,都是应用雷同的思路来实现。咱们来具体实际一下,这里咱们须要用到 @element-plus/icons-vue
,先装置一下:
# NPMnpm install @element-plus/icons-vue# Yarnyarn add @element-plus/icons-vue
而后在 main.js 中导入:
import * as ElementPlusIconsVue from '@element-plus/icons-vue'const app = createApp(App)for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component)}
在 components
目录下新建 DynamicModifyTable.vue
:
<template> <div> <h2>Vue3 + Element plus 动静批改表格</h2> <h3>「卡拉云 - 极速搭建企业外部工具,十倍晋升开发效率」</h3> <el-table :data="tableData" style="width: 100%"> <el-table-column :prop="item.prop" :label="item.label" v-for="(item, index) in tableHeader" :key="item.prop" > <template #default="scope"> <div v-show="item.editable || scope.row.editable" class="editable-row" > <template v-if="item.type === 'input'"> <el-input size="small" v-model="scope.row[item.prop]" :placeholder="`请输出${item.label}`" @change="handleEdit(scope.$index, scope.row)" /> </template> <template v-if="item.type === 'date'"> <el-date-picker v-model="scope.row[item.prop]" type="date" value-format="YYYY-MM-DD" :placeholder="`请输出${item.label}`" @change="handleEdit(scope.$index, scope.row)" /> </template> </div> <div v-show="!item.editable && !scope.row.editable" class="editable-row" > <span class="editable-row-span">{{ scope.row[item.prop] }}</span> <el-popover placement="right" :width="120" trigger="hover" content="this is content, this is content, this is content" > <template #reference> <el-icon class="icon" :size="18"> <Edit /> </el-icon> </template> <div class="menu-list"> <div class="menu-item" @click="prepend(scope.$index)" > 上方插入一行 </div> <div class="menu-item divider" @click="append(scope.$index)" > 下方插入一行 </div> <div class="menu-item" @click="deleteCurrentColumn(index)"> 删除当前列 </div> <div class="menu-item" @click="insertBefore(index)"> 后方插入一列 </div> <div class="menu-item" @click="insertAfter(index)"> 前方插入一列 </div> </div> </el-popover> </div> </template> </el-table-column> <el-table-column label="操作"> <template #default="scope"> <el-button v-show="!scope.row.editable" size="small" @click="scope.row.editable = true" >编辑</el-button > <el-button v-show="scope.row.editable" size="small" type="success" @click="scope.row.editable = false" >确定</el-button > <el-button size="small" type="danger" @click="handleDelete(scope.$index)" >删除</el-button > </template> </el-table-column> </el-table> </div></template><script>const item = { name: '', birth: '', province: "", city: "", address: '', phone: "",}const header = { prop: "key", label: "自定义", editable: false, type: "input",}export default { name: "DynamicModifyTable", data() { return { tableHeader: [ { prop: "name", label: "姓名", editable: false, type: "input", }, { prop: "birth", label: "生日", editable: false, type: "date" }, { prop: "phone", label: "电话", editable: false, type: "input" }, { prop: "province", label: "省份", editable: false, type: "input" }, { prop: "city", label: "市区", editable: false, type: "input" }, { prop: "address", label: "具体地址", editable: false, type: "input" } ], tableData: [{ name: '张三', province: "上海市", city: "普陀区", address: "金沙江路 1518 弄", birth: '2016-05-02', phone: "12345678910", }, { name: '李四', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1517 弄', age: 19, phone: "12345678911", }, { name: '王五', birth: '2016-05-01', province: "上海市", city: "普陀区", address: '金沙江路 1519 弄', phone: "12345678912", }, { name: '赵六', birth: '2016-05-03', province: "上海市", city: "普陀区", address: '金沙江路 1516 弄', phone: "12345678913", }] } }, methods: { handleEdit(row) { row.editable = true; }, handleDelete(index) { this.tableData.splice(index, 1); }, prepend(index) { item.editable = true this.tableData.splice(index, 0, item); }, append(index) { item.editable = true this.tableData.splice(index + 1, 0, item); }, deleteCurrentColumn(index) { this.tableHeader.splice(index, 1); }, insertBefore(index) { header.editable = true; this.tableHeader.splice(index, 0, header);
Vue3 + Element Plus 创立动静多级表头
多级表头的实现比较简单,次要是通过 el-table-column
的嵌套来实现的,在 components
目录下新建 MultiHeaderTable.vue
文件:
<template> <div> <h2>Vue3 + Element plus 动静表格</h2> <el-table :data="tableData" style="width: 100%"> <el-table-column :prop="item.prop" :label="item.label" v-for="(item, index) in tableHeader" :key="index" > <el-table-column :prop="child.prop" :label="child.label" v-for="(child, childIndex) in item.children" :key="childIndex" ></el-table-column> </el-table-column> </el-table> </div></template><script>export default { name: "MultiHeaderTable", data() { return { tableHeader: [ { prop: "name", label: "姓名", }, { prop: "birth", label: "生日", }, { prop: "phone", label: "电话", }, { label: "地址", children: [ { prop: "province", label: "省份", }, { prop: "city", label: "市区", }, { prop: "address", label: "具体地址", } ] } ], tableData: [{ name: '张三', province: "上海市", city: "普陀区", address: "金沙江路 1518 弄", birth: '2016-05-02', phone: "12345678910", }, { name: '李四', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1517 弄', age: 19, phone: "12345678911", }, { name: '王五', birth: '2016-05-01', province: "上海市", city: "普陀区", address: '金沙江路 1519 弄', phone: "12345678912", }, { name: '赵六', birth: '2016-05-03', province: "上海市", city: "普陀区", address: '金沙江路 1516 弄', phone: "12345678913", }] } },}</script>对于 `tableHeader` 的定义,咱们通过 `children` 字段来指定当前列的二级表头,然而会发现成果并不是咱们预期的那样:这是为什么呢?原来是因为 `el-table-column` 会检测外部是否还有 `el-table-column`,如果有的话,默认会显示内层的 `el-table-column`,然而在一级表头的状况下,内层 `el-table-column` 并没有值。所以咱们须要简略批改一下代码,那就是通过 `v-if="item.children"` 来判断当前列是否有二级表头:```html<template v-if="item.children"> <el-table-column :prop="child.prop" :label="child.label" v-for="(child, childIndex) in item.children" :key="childIndex" ></el-table-column></template>
如果不这么做,那就只能渲染有二级表头的列,无奈失常显示一级表头的数据, 最初的成果如下:
扩大浏览:《12款最棒的 Vue ui 组件库框架 举荐测评》
Vue3 + Element Plus 表格中单元格行合并
咱们先来看下如何实现行合并,行合并或者是列合并,都须要用到 el-table
中 span-method
这个办法,在官网的例子中,是通过固定返回 rowspan
,colspan
来实现行合并的:
const objectSpanMethod = ({ row, column, rowIndex, // 须要合并的开始行 columnIndex, // 须要合并的列}) => { if (columnIndex === 0) { if (rowIndex % 2 === 0) { return { rowspan: 2, //合并的行数 colspan: 1, //合并的列数 } } else { return { rowspan: 0, colspan: 0, } } }}
然而在动态数据的场景下,这种办法就不实用了,因为前端的表格数据往往是后端通过接口返回的。比方咱们有以下数据结构:
tableData: [{ name: '张三', province: "上海市", city: "普陀区", address: "金沙江路 1518 弄", birth: '2016-05-02', phone: "12345678910",}, { name: '李四', birth: '2016-05-02', province: "上海市", city: "普陀区", address: '金沙江路 1517 弄', age: 19, phone: "12345678911",}, { name: '王五', birth: '2016-05-03', province: "上海市", city: "普陀区", address: '金沙江路 1519 弄', phone: "12345678912",}, { name: '赵六', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1516 弄', phone: "12345678913",}, { name: '孙七', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1516 弄', phone: "12345678913",}, { name: '周八', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1516 弄', phone: "12345678913",}, { name: '吴九', birth: '2016-05-06', province: "上海市", city: "普陀区", address: '金沙江路 1516 弄', phone: "12345678913",}]
咱们的需要是把雷同 birth
进行合并。在 components
目录下新建 RowMergeTable.vue
文件:
<template> <div> <h2>Vue3 + Element plus 动静行合并表格</h2> <el-table :data="tableData" style="width: 100%" :span-method="objectSpanMethod" border > <el-table-column :prop="item.prop" :label="item.label" v-for="(item, index) in tableHeader" :key="index" ></el-table-column> </el-table> </div></template><script>export default { name: "RowMergeTable", data() { this.spanArr = []; return { tableHeader: [ { prop: "birth", label: "生日", }, { prop: "name", label: "姓名", }, { prop: "phone", label: "电话", }, { prop: "province", label: "省份", }, { prop: "city", label: "市区", }, { prop: "address", label: "具体地址", } ], tableData: [{ name: '张三', province: "上海市", city: "普陀区", address: "金沙江路 1518 弄", birth: '2016-05-02', phone: "12345678910", }, { name: '李四', birth: '2016-05-02', province: "上海市", city: "普陀区", address: '金沙江路 1517 弄', age: 19, phone: "12345678911", }, { name: '王五', birth: '2016-05-03', province: "上海市", city: "普陀区", address: '金沙江路 1519 弄', phone: "12345678912", }, { name: '赵六', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1520 弄', phone: "12345678913", }, { name: '孙七', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1521 弄', phone: "12345678913", }, { name: '周八', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1522 弄', phone: "12345678913", }, { name: '吴九', birth: '2016-05-06', province: "上海市", city: "普陀区", address: '金沙江路 1523 弄', phone: "12345678913", }] } }, created() { this.getSpanArr(this.tableData); }, methods: { getSpanArr(data) { for (var i = 0; i < data.length; i++) { if (i === 0) { this.spanArr.push(1); this.pos = 0 } else { if (data[i].birth === data[i - 1].birth) { this.spanArr[this.pos] += 1; this.spanArr.push(0); } else { this.spanArr.push(1); this.pos = i; } } } }, objectSpanMethod({ rowIndex, columnIndex }) { if (columnIndex === 0) { const _row = this.spanArr[rowIndex]; const _col = _row > 0 ? 1 : 0; return { rowspan: _row, colspan: _col } } } }}</script>
下面的例子就实现了行合并的性能:
因为表格的数据是动静的,所以咱们须要当时通过计算,来得悉哪些行是须要合并的,这里就是通过 getSpanArr
办法来实现的,全局保护了一个 spanArr
变量,用于记录每一行须要合并的数字,pos
是 spanArr
的索引,这样就能够依据索引来动静设置须要合并的行树。当 i === 0
,阐明是第一行数据,向 spanArr
数组中 push
1,当 i !== 0
,此时就须要比拟以后行与前一行数据的 birth
是否相等,如果相等,则利用索引,批改以后行须要合并的行数。
objectSpanMethod
办法,在 el-table
渲染每一行数据的时候都会执行,这样就能够通过 rowIndex
来获取每一行须要合并的行数信息,来实现行合并的性能。
那么如何实现多行合并?其实也是一样的思路,通过 spanMap
能够存储多个列的行合并信息。在 components
下新建 MultiRowMergeTable.vue
:
<template> <div> <h2>Vue3 + Element plus 动静多行合并表格</h2> <el-table :data="tableData" style="width: 100%" :span-method="objectSpanMethod" border > <el-table-column :prop="item.prop" :label="item.label" v-for="(item, index) in tableHeader" :key="index" ></el-table-column> </el-table> </div></template><script>export default { name: "MultiRowMergeTable", data() { this.spanMap = {}; this.mergedColumns = ["birth", "province", "city"] return { tableHeader: [ { prop: "birth", label: "生日", }, { prop: "name", label: "姓名", }, { prop: "phone", label: "电话", }, { prop: "province", label: "省份", }, { prop: "city", label: "市区", }, { prop: "address", label: "具体地址", } ], tableData: [{ name: '张三', province: "上海市", city: "普陀区", address: "金沙江路 1518 弄", birth: '2016-05-02', phone: "12345678910", }, { name: '李四', birth: '2016-05-02', province: "上海市", city: "普陀区", address: '金沙江路 1517 弄', age: 19, phone: "12345678911", }, { name: '王五', birth: '2016-05-03', province: "上海市", city: "普陀区", address: '金沙江路 1519 弄', phone: "12345678912", }, { name: '赵六', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1520 弄', phone: "12345678913", }, { name: '孙七', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1521 弄', phone: "12345678913", }, { name: '周八', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1522 弄', phone: "12345678913", }, { name: '吴九', birth: '2016-05-06', province: "上海市", city: "普陀区", address: '金沙江路 1523 弄', phone: "12345678913", }] } }, created() { this.getSpanArr(this.tableData); }, methods: { getSpanArr(data) { for (var i = 0; i < data.length; i++) { if (i === 0) { this.mergedColumns.forEach(column => { this.spanMap[column] = { spanArr: [1], pos: 0 } }) } else { this.mergedColumns.forEach(column => { if (data[i][column] === data[i - 1][column]) { this.spanMap[column].spanArr[this.spanMap[column].pos] += 1; this.spanMap[column].spanArr.push(0) } else { this.spanMap[column].spanArr.push(1); this.spanMap[column].pos = i; } }) } } }, objectSpanMethod({ column, rowIndex }) { if (this.spanMap[column.property]) { const _row = this.spanMap[column.property].spanArr[rowIndex]; const _col = _row > 0 ? 1 : 0; return { rowspan: _row, colspan: _col } } } }}</script>
实现成果如下:
动静多行合并的需要往往更常见,须要把每一列中,雷同的数据进行合并,都能够参照这个思路来实现。
扩大浏览:《Vue + Node.js 全栈开发实战教程 - 手把手教你搭建「文件上传」治理后盾》
Vue3 + Element Plus 表格中单元格列合并
接下来,咱们来看下如何实现列的合并,其实思路是和行合并相似的,也须要用到 span-method
这个办法,惟一不同的在于,列合并须要解决被合并列的原始数据,否则被合并列的原始数据会填充到合并之后的表格里,这样说可能有点形象,咱们写来写一个例子,在 components 下新建 ColumnMergeTable.vue:
<template> <div> <h2>Vue3 + Element plus 动静表格列合并</h2> <el-table :data="tableData" style="width: 100%" :span-method="objectSpanMethod" border > <el-table-column :prop="item.prop" :label="item.label" v-for="(item, index) in tableHeader" :key="index" ></el-table-column> </el-table> </div></template><script>export default { name: "ColumnMergeTable", data() { return { tableHeader: [ { prop: "birth", label: "生日", }, { prop: "name", label: "姓名", }, { prop: "phone", label: "电话", }, { prop: "province", label: "省份", }, { prop: "city", label: "市区", }, { prop: "address", label: "具体地址", } ], tableData: [{ name: '张三', province: "上海市", city: "普陀区", address: "金沙江路 1518 弄", birth: '2016-05-02', phone: "12345678910", }, { name: '李四', birth: '2016-05-02', province: "上海市", city: "普陀区", address: '金沙江路 1517 弄', age: 19, phone: "12345678911", }, { name: '王五', birth: '2016-05-03', province: "上海市", city: "普陀区", address: '金沙江路 1519 弄', phone: "12345678912", }, { name: '赵六', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1520 弄', phone: "12345678913", }, { name: '孙七', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1521 弄', phone: "12345678913", }, { name: '周八', birth: '2016-05-04', province: "上海市", city: "普陀区", address: '金沙江路 1522 弄', phone: "12345678913", }, { name: '吴九', birth: '2016-05-06', province: "上海市", city: "普陀区", address: '金沙江路 1523 弄', phone: "12345678913", }] } }, methods: { objectSpanMethod({ rowIndex, columnIndex }) { // 暗藏第二行或者第三行的列 if (rowIndex === 1 || rowIndex === 2) { // 合并第二行 if (columnIndex === 1) { // 从第二列开始 return [1, 3] //或者返回如下模式也能够 // return { // rowspan: 1, // colspan: 3 // } // 这里的 else if 即便用来解决被合并列的原始数据的状况,须要暗藏原始单元格 } else if (columnIndex === 2 || columnIndex === 3) { return [0, 0] } } } }}</script>
能够看进去,列合并其实比行合并简略一些,返回一个数组更容易了解一些,数组的第一项示意合并的起始列,第二项示意合并的终止列,其区间的所有列都会合并成一列,被合并的列还须要通过 [0, 0] 来暗藏对应的单元格,这个是和行合并不同的中央。
扩大浏览:《Vue echarts 应用教程》
Vue3 + Element Plus 动静表格源代码
本教程所写源代码可在咱们的 github 上找到。
动静表格与卡拉云
本文具体解说如何 Vue3 + Element Plus 中如何创立动静表格的问题。其实如果你基本不想解决简单的前端问题,齐全能够应用卡拉云来解决前端表格,卡拉云内置表格组件,间接鼠标拖拽即可生成,不仅能够解决动静表格,内容实时编辑以及表格中展现图片等性能,还有弱小的过滤筛选、数据导出性能。
卡拉云可帮你疾速搭建企业外部工具,下图为应用卡拉云搭建的外部广告投放监测零碎,无需懂前端,仅需拖拽组件,10 分钟搞定。你也能够疾速搭建一套属于你的后盾管理工具。
卡拉云是新一代低代码开发平台,与前端框架 Vue、React等相比,卡拉云的劣势在于不必首先搭建开发环境,间接注册即可开始应用。开发者齐全不必解决任何前端问题,只需简略拖拽,即可疾速生成所需组件,可一键接入常见数据库及 API,依据疏导简略几步买通前后端,数周的开发工夫,缩短至 1 小时。立刻收费试用卡拉云。
扩大浏览:
- Vue form 表单异步验证终极教程
- 最好用的 6 款 MongoDB GUI 管理工具横向测评
- 5 款最棒的 Vue UI 挪动端组件库 - 特地针对国内应用场景举荐
- 顶级好用的 5 款 Vue table 表格组件测评与举荐
- Retool 是什么,怎么样? —— Retool 低代码开发平台测评