小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
先来看一个需求
1.表格可多选
2.表格可排序
3.表格可拖动列宽
4.表格固定列和表头
5.表格列顺序可调整
6.表格列可隐藏或显示
7.表格设置需要实时保存
解决思路
其中[1、2、3、4 ] Element-UI table
组件原生就支持的
[5] 列顺序可调整 可以通过 改变 el-table-column
的渲染顺序实现
[6] 可以通过控制 el-table-column
的展示与隐藏实现
[7] 将每次修改存至本地localStorage
Table组件 地址:element.eleme.io/#/zh-CN/com…
上代码:
核心在于需要循环渲染 el-table-column
<template>部分
<!--列设置按钮-->
<el-dropdown trigger="click">
<el-button icon="el-icon-s-operation" size="mini">列设置</el-button>
<el-dropdown-menu slot="dropdown">
<span class="title">列设置</span>
<el-tree draggable :data="columns" :props="defaultProps" :allow-drop="allowDrop" @node-drop="handleDrop">
<span class="tree-table-setting" slot-scope="{ node, data }">
<el-switch @change="saveTableColumns" v-model="data.show"> </el-switch>
<span>{{ node.label }}</span>
</span>
</el-tree>
</el-dropdown-menu>
</el-dropdown>
<!--表格-->
<div>
<el-table
:key="tableKey"
:data="tableData"
:height="tableHeight"
:row-style="{ height: '40px' }"
:cell-style="{ borderRight: 'none' }"
:header-cell-style="{ height: '40px', padding: 0, background: '#f6f8fa', color: '#333' }"
@row-click="handelTableClick"
@selection-change="handleSelectionChange"
@header-dragend="surverWidth"
border
size="mini"
tooltip-effect="dark"
highlight-current-row
>
<el-table-column align="center" type="selection"> </el-table-column>
<template v-for="item in columns">
<el-table-column
v-if="item.show"
show-overflow-tooltip
:prop="item.prop"
:sortable="item.sortable"
:label="item.label"
:width="item.width"
:key="item.prop"
:resizable="item.resizable"
>
<template slot-scope="scope">
<span v-if="item.prop === 'clue_type'">{{ scope.row[item.prop] | clueType }}</span>
<span v-else-if="item.prop === 'clue_source'">{{ scope.row[item.prop] | clueSource }}</span>
<span v-else-if="item.prop === 'contact_type'">{{ scope.row[item.prop] | commonType }}</span>
<span v-else-if="item.prop === 'company_name'" class="link">{{ scope.row[item.prop] }}</span>
<span v-else>{{ scope.row[item.prop] }}</span>
</template>
</el-table-column>
</template>
<!-- 固定列 -->
<el-table-column fixed="right" label="关注" width="56">
<template slot-scope="scope">
<el-button
style="height: 10px;padding:0; margin:0;"
type="text"
@click.native.stop="clueTableRowClick(scope.row, 'collect')"
size="mini"
>
<img v-if="scope.row.collect === 1" style="width:16px" src="@/assets/star1.png" />
<img v-else style="width:16px" src="@/assets/star0.png" />
</el-button>
</template>
</el-table-column>
<el-table-column fixed="right" label="编辑" width="56">
<template slot-scope="scope">
<el-button
style="height: 10px;padding:0; margin:0;"
type="text"
@click.native.stop="clueTableRowClick(scope.row, 'edit')"
size="mini"
>
<img style="width:16px" src="@/assets/edit.png" />
</el-button>
</template>
</el-table-column>
<el-table-column> </el-table-column>
</el-table>
</div>
注意事项
1.控制el-table-column显示与隐藏使用v-show无效,需要使用v-if。
2.部分列需要使用过滤器 我这里使用了if做判断。
3.由于虚拟Dom算法导致有时表格并不会实时刷新,这里需要给table添加key值。
4.列设置中可上下拖动采用 Tree组件。
5.由于需要固定列和表头 每次获取到表格数据后,再给tableHight赋值。
const winHeight = document.body.clientHeight
// 窗口大小 - 表格顶部高度
this.tableHeight = winHeight - 260
6.这里由于给row绑定了click事件,需要给row中的Button按钮添加.native
修饰,防止事件冒泡添加.stop
修饰。
<script>部分
export default {
data() {
// 表格key
tableKey: 1,
// 表格数据
tableData: [],
// 默认表格高度
tableHeight:600,
// 表格展示项配置
columns:[
{
prop: 'name', // 对应列内容的字段名
label: '姓名', // 显示的标题
width: 66, // 对应列的宽度
resizable: true, // 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真)
show: true, // 展示与隐藏
sortable: false // 对应列是否可以排序
},
{
prop: 'clue_type',
label: '线索类型',
width: 78,
resizable: true,
show: true,
sortable: false
},
// ... 省略部分字段
],
// 列设置中 tree配置
defaultProps: {
children: 'children',
label: 'label'
}
},
mounted(){
this.init()
},
methods: {
init() {
// 判断本地是否有表格配置数据 ? 加载 : 忽略
// 获取表格数据
// 重设表格高度
},
allowDrop(draggingNode, dropNode, type) {
// 仅允许Tree节点上下拖动
return type !== 'inner'
},
// Tree 拖动时更新表格
handleDrop() {
this.tableKey++
// 保存表格配置
this.saveTableColumns()
},
// 重置表格列设置
resetTable() {
// ... 忽略
},
// 显示隐藏切换 && 保存表格配置
saveTableColumns() {
// setStorage 封装了 localStorage
setStorage('clueTable', this.columns)
},
// 选中表格行
handelTableClick(row) {
// ... 省略业务逻辑
},
// table多选操作
handleSelectionChange(val) {
// ... 省略业务逻辑
},
// 表头拖动事件
surverWidth(newWidth, oldWidth, column, event) {
this.columns = this.columns.map(v => {
if (v.prop === column.property) v.width = newWidth
return v
})
this.saveTableColumns()
},
// 关注与编辑操作
clueTableRowClick(val, type) {
// ... 省略业务逻辑
}
}
}
以上就是该需求的简单实现。
END
「欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章」。