vue element内嵌table
一天无聊 人气:0在大四实习工作中碰到一个比较特别的需求,要求在一个 table 表格中点击一条数据的编号,在该条数据下方出现一个新的 table 表格。这个需求在 element UI 的官方文档中也有案例,以下是参考了其他博客(找不到博客地址了)和 element UI 之后的最终实现效果。
效果图
不知道是公司电脑比较拉,还是软件问题导致录制出来的动态图很卡,但是在实际操作并不会卡。
代码:
页面显示代码:
主要代码在于 <el-table-column type="expand" width="1" >
type="expand"
官方解释:
通过设置 type="expand" 和 Scoped slot 可以开启展开行功能,el-table-column 的模板会被渲染成为展开行的内容,展开行可访问的属性与使用自定义列模板时的 Scoped slot 相同。
而最后通过 width="1"
将 el-table-column
设置为 type="expand"
之后自带显示的 箭头 图标隐藏。
整个代码流程大致如下:
数据表分为 主表和子表,页面最开始加载时展示主表 table 数据(也就是普通的 table 数据表格,就叫它主 table )。当我点击主 table 中的一行数据的导航名称时,触发一个点击事件 toogleExpand()
。这个事件的主要功能是根据点击数据的 ID 去后台查找与其对应的子表数据返回到前端,最后前端在进行展示。
这过程比较值得注意的是,拿到对应数据的子表数据之后,怎么与主表数据一一绑定。
这里我是通过使用 Map 的方式实现的,通过以主表 ID 为 key ,子表数据为 value .
// 使用 map 结构的方式保存翻译列表 this.WebsiteLangMap.set(id,response.rows)
到了这一步还存在一个问题。
在页面刚加载的时候第一次点击打开对应的内嵌 table 是没有数据的,只有第二次点击打开才会有数据。
因为是 table 第一次渲染的时候 我们保存的子表数据的 Map 是没有数据的,所以第一次点击并不会显示数据(没有数据怎么渲染)。而我们获取数据是在点击事件 toogleExpand()
触发之后会请求到的数据。也就是先渲染后才有数据。原先我以为它能像监听器一样,能实时监听 data
的变化而渲染页面,然而并不能。
解决办法是:控制 el-table
的 key 属性,在子表数据发生变化是改变的 key 的值。
this.websiteLangTableKey = !this.websiteLangTableKey;
以下是核心代码:
<el-table v-loading="loading" :data="websiteList" @selection-change="handleSelectionChange" ref="table" key="websiteTable" row-key="id" style="width: 100%; maigin-bottom: 20px;" border > <el-table-column type="selection" width="55" align="center" /> <!-- <el-table-column :label="td('主键')" align="center" prop="id" /> --> <el-table-column :label="td('上级导航')" align="center" prop="parentId" /> <el-table-column :label="td('导航名称')" align="center" prop="barName" > <template slot-scope="scope" > <el-link type="primary" :underline="false" @click="toogleExpand(scope.row)" > {{scope.row.barName}} </el-link> </template> </el-table-column> <el-table-column :label="td('是否链接')" align="center" prop="isLink" /> <el-table-column :label="td('链接地址')" align="center" prop="url" /> <el-table-column :label="td('创建日期')" align="center" prop="createTime" /> <el-table-column :label="td('创建用户')" align="center" prop="createBy" /> <el-table-column :label="td('更新时间')" align="center" prop="updateTime" /> <el-table-column :label="td('更新用户')" align="center" prop="updateBy" /> <el-table-column :label="td('备注')" align="center" prop="remark" /> <el-table-column :label="td('操作')" align="center" width="130" class-name="small-padding fixed-width" fixed="right"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['cms:website:edit']" >{{td("修改")}} </el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['cms:website:remove']" >{{td("删除")}}</el-button> </template> </el-table-column> <el-table-column type="expand" width="1" > <template slot-scope="scope"> <el-table v-loading="loading" style="width: 100%" row-key="langId" :key="websiteLangTableKey" :data="WebsiteLangMap.get(scope.row.id)" class="table-in-table" > <!-- <el-table-column :label="td('ID主键')" align="center" prop="langId" /> --> <!-- <el-table-column :label="td('导航ID')" align="center" prop="webId" /> --> <el-table-column :label="td('语言编号')" align="center" prop="langCode" /> <el-table-column :label="td('语言名称')" align="center" prop="langName" /> <el-table-column :label="td('中文')" align="center" prop="langCn" /> <el-table-column :label="td('语言翻译')" align="center" prop="langTranslate" /> <el-table-column :label="td('备注')" align="center" prop="remark" /> <el-table-column :label="td('操作')" align="center" width="130" class-name="small-padding fixed-width" fixed="right"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdateLang(scope.row)" v-hasPermi="['cms:websiteLang:edit']" >{{td("修改")}} </el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDeleteLang(scope.row)" v-hasPermi="['cms:websiteLang:remove']" >{{td("删除")}}</el-button> </template> </el-table-column> </el-table> </template> </el-table-column> </el-table>
// 内嵌 table toogleExpand(row) { this.getListLang(row.id); let $table = this.$refs.table; $table.toggleRowExpansion(row) }, /** 查询导航翻译列表 */ getListLang(id) { // 根据 导航ID 获取翻译列表 this.LangQueryParams.webId = id; listWebsiteLang(this.LangQueryParams).then(response => { // 使用 map 结构的方式保存翻译列表 this.WebsiteLangMap.set(id,response.rows) this.websiteLangTableKey = !this.websiteLangTableKey; this.resetLang(); }); },
<style lang="scss" scoped> .app-container { ::v-deep { .el-table th { background: #ddeeff; } .el-table__expanded-cell { border-bottom: 0px; border-right: 0px; padding: 0px 0px 0px 47px; } } .table-in-table { border-top: 0px; } } </style>
加载全部内容