0


element-ui表格自定义动态列

element-ui表格自定义动态列

实现效果

fd70c05c63b7784e53baff1c825f6b2.png
Snipaste_2023-02-17_11-51-56.png

具体功能

  1. 拖拽表头改变宽度 1. 限制最小宽度, 实时保存设置。
  2. 隐藏列 1. 选中列隐藏, 不显示在表格中。2. “勾选” 列和"操作" 列不可隐藏, 并且不包含在列控制组件中。3. 隐藏后, 无论是否冻结均不显示。有特殊标识则要另外做判断。
  3. 列冻结 1. 开启时, 表示选中列靠左冻结。2. 只有"操作" 列允许靠右冻结且禁止更改。3. 列按照冻结>不冻结的顺序动态排序。
  4. 列拖动排序 1. 拖动结束按照冻结>不冻结的顺序自动排序。
  5. 恢复默认配置 1. 恢复表格的默认配置, 清除用户的自定义设置。
  6. 保存 1. 只有保存后用户的相关设置才会生效(包含隐藏列, 列冻结和列拖动排序)。
  7. 取消 1. 不保存用户的相关设置(包含隐藏列, 列冻结和列拖动排序)。

实现原理

相关数据格式

// 利用当前页面路由name值当作唯一标识, 存储到数据库中
pathSign: 'DataGnGoodsReport'

// 表头数据格式
[{"isFixed":"false","isSortable": false,"label":"所属部门","minWidth": 108,"show": true,"specialMask":"isStoreSp",    // 特殊标识, 可用于该特殊标识和show 双层判断隐藏该列, 需要做字符串转变量的处理
        "value":"departId",    // 值标识
        "width": 108
    }
]

页面配置

// 页面Table
<el-table
  border    // 边框
  row-key="id":data="tableDataFormat":row-style="{'height': '100%'}"
  @sort-change="sortChange"    // 排序方法
  @header-dragend="headerDragend"    // 表头拖拽方法
>
    // 根据表头数组动态渲染数据
    <template v-for="(item, index) in renderArr">
      <el-table-column
        v-if="item.specialMask ? item.show && strToVariable(item.specialMask) : item.show"    // 是否显示:key="index"resizable:prop="item.value"    // 列的值:label="item.label"    // 表头文案:min-width="item.minWidth"    // 最小宽度:width="item.width"    // 宽度:fixed="item.isFixed === 'false' ? false : item.isFixed"    // 是否冻结:align="item.align || 'center'"    // 文本对齐方式:sortable="item.isSortable && 'custom'"    // 当前列是否可排序(升降序)
      >   
          <template #default="{row}">

                    /* 根据显示类型不同, 做不同处理 */<span v-if="item.value == name">{{ row[item.value] }}</span>
            ......

          </template>
        </el-table-column>
    </template>
</el-table>

// 引入列控制组件
<column-control ref="columnControl":visible.sync="columnControlDialogVisible":render-arr.sync="renderArr" @save="saveRenderArr" />

拖拽表头改变宽度

鼠标悬浮在表头上方才显示右边框

.table-container >>> .el-table--border th{
  border-right: none;
}
.table-container >>> .el-table__header th:hover {
  border-right: 1px solid #939599;
}
.table-container >>> .el-table--border td{
  border: 0!important;
}

表头拖拽

// 表头拖拽, 使用表格header-dragend钩子完成headerDragend(newWidth, oldWidth, column, event){const item =this.renderArr.find(item=> item.label === column.label)// 取最小宽度if(newWidth <= item.minWidth){
    column.width = item.minWidth
  }else{
    item.width =parseInt(column.width)}// 保存配置this.saveRenderArr(this.renderArr)},

列控制组件封装

HTML

<template><el-dialog
    title="列控制":visible.sync="visible"
    width="60%"
    top="4vh":before-close="handleColumnControl"><div class="table-column"><el-table
        ref="columnTable"
        row-key="label":data="renderArrCopy"
        height="70vh":row-style="{'height': '100%'}"><el-table-column
          label="#"
          type="index"
          width="50"/><el-table-column
          prop="label"
          label="列名"/><el-table-column
          prop="show"
          label="隐藏列"><template slot-scope="{row}">// 隐藏值取反判断<el-switch v-model="row.show":active-value="false":inactive-value="true"/></template></el-table-column><el-table-column
          prop="show"
          label="列冻结"><template slot-scope="{row}"><el-select v-model="row.isFixed" placeholder="请选择":disabled="row.value === 'action'" @change="sortRenderArr"><el-option
                v-for="item in options":key="item.value":label="item.label":value="item.value"/></el-select></template></el-table-column><el-table-column
          label="拖动排序"
          align="center"><svg-icon icon-class="drag2"class="drag-icon move"/></el-table-column></el-table></div><div class="submit-box"><el-button @click="handleColumnControl">取消</el-button><el-button type="primary" @click="save">保存</el-button></div><div class="default-box" @click="restoreDefault">恢复出厂设置</div><div class="tips">表格列根据 冻结>不冻结 的顺序排序</div></el-dialog></template>

JS

<script>import Sortable from'sortablejs'import{ deepClone }from'@/utils/index'exportdefault{name:'ColumnControl',props:{visible:{type: Boolean,default:false},renderArr:{type: Array,default:function(){return[]}}},data(){return{options:[{value:'left',label:'冻结'},{value:'false',label:'不冻结'}],renderArrCopy:[]// 拷贝的表头数据}},computed:{},watch:{visible:function(newVal, oldVal){
      newVal &&this.rowDrop()this.deepClone()}},methods:{// 深拷贝deepClone(){// 组件内部表头数据和页面表头数据分离this.renderArrCopy =deepClone(this.renderArr)},// 列拖动排序rowDrop(){this.$nextTick(()=>{// 要侦听拖拽响应的DOM对象const tbody = document.querySelector('.table-column .el-table__body-wrapper .el-table__body tbody')const _this =this
        Sortable.create(tbody,{animation:20,// 结束拖拽后的回调函数onEnd({ newIndex, oldIndex }){const currRow = _this.renderArrCopy.splice(oldIndex,1)[0]
            _this.renderArrCopy.splice(newIndex,0, currRow)const timer =setTimeout(()=>{
              _this.sortRenderArr()clearTimeout(timer)},0)}})// 删除最后一项操作('操作' 列项不显示在该组件中。因数据上需要保留该项, 所以不可采用删除数据的方法来达到该效果, 只能从页面渲染做隐藏处理)const lastIndex =this.renderArrCopy.length -1if(this.renderArrCopy[lastIndex].label ==='操作'){// 获取'操作'项的那一行并删除const rows = document.querySelectorAll('.table-column .el-table__row')// 类数组转为数组
          Array.from(rows).forEach((item, index)=>{
            index === lastIndex && item.remove()})}})},// 按冻结 > 不冻结排序sortRenderArr(){this.renderArrCopy.sort((star, next)=>{const arr =['left','false']return arr.indexOf(star.isFixed)- arr.indexOf(next.isFixed)})},// 取消handleColumnControl(){this.$emit('update:visible',false)},// 保存asyncsave(){this.$emit('update:renderArr',this.renderArrCopy)this.handleColumnControl()this.$emit('save',this.renderArrCopy)},// 恢复默认配置restoreDefault(){this.$emit('save',[])}}}</script>

全局方法

import{ getRenderArr, saveRenderArr }from'@/api/common'exportconst columnControlMixin ={data(){return{renderArr:[],// 动态列表头数组columnControlDialogVisible:false,// 动态列组件显示设置}},computed:{// 字符串转变量strToVariable(){returnfunction(text){returnthis[text]}}},created(){// 获取表头数据this.getRenderArr()},methods:{// 表头拖拽headerDragend(newWidth, oldWidth, column, event){const item =this.renderArr.find(item=> item.label === column.label)if(newWidth <= item.minWidth){
        column.width = item.minWidth
      }else{
        item.width =parseInt(column.width)}this.saveRenderArr(this.renderArr)},// 根据name值获取表头数据asyncgetRenderArr(){try{const res =awaitgetRenderArr({pathSign:this.$route.name
        })if(res.code ===200){this.renderArr = res?.data
        }}catch(error){
        console.log(error)}},// 保存页面表头数据和重置asyncsaveRenderArr(arr){try{awaitsaveRenderArr({pathSign:this.$route.name,content: arr ||[]})if(!arr.length){awaitthis.getRenderArr()// 列控制组件重新拷贝数据awaitthis.$refs.columnControl.deepClone()this.$message({message:'恢复出厂设置成功',type:'success'})}}catch(error){
        console.log(error)}}}}
标签: vue.js elementui 前端

本文转载自: https://blog.csdn.net/weixin_43218691/article/details/129087987
版权归原作者 终生耕田 所有, 如有侵权,请联系我们删除。

“element-ui表格自定义动态列”的评论:

还没有评论