4

关于 element-ui 使用中的其他问题请 点这里

一、el-table 翻页序号连续

// 方法一
<el-table-column label="序号" type="index" width="50" align="center">
      <template v-slot="{ $index }">
          <span>{{ $index + pageSize * ( currentPage - 1 ) + 1 }}</span>
      </template>
</el-table-column>

// $index 当前序号  pageSize 每页显示的条数  currentPage 当前页码
// 方法二
<el-table-column label="序号" type="index" width="50" align="center" :index="tableIndex"/>

// 文档中index的类型可以是Function(index),这里绑定一个方法,将返回值赋给index, 即该行的索引

...
methods: {
    tableIndex(index) {
        return index + this.pageSize * ( this.currentPage - 1 ) + 1
    }
}

二、el-table el-pagination 分页页数从0开始

项目中的需求:后端返回的接口数据是从第0页开始的,el-pagination 中当前页数默认是从1开始的,也就是点击el-pagination的第1页传递给后端的页数是0,点击第2页传递1,点击第3页传递2 ... ...

<el-pagination
    background
    :current-page="currentPage"
    :page-size="pageSize" />
        
export default{
    data() {
        return {
            currentPage: 1, // 当前页数
            pageSize: 10, // 每页显示条目个数
        }
    },
    computed: {
        queryParams () {
            return {
                page: this.currentPage - 1,
                size: this.pageSize
            }
        }
    }
}
// 调用接口的时候把queryParams传递过去就可以了

三、el-table 使用 v-loading 报错

在项目中按需引入element-ui的时候,使用 el-table 的v-loading 报错,如下:

image-20200715164002225.png

github 上也有相关 issues,点这里查看

解决方法很简单,在 main.js 中将 loading 引入 use 一下就好了,我是将 element 按需引入的组件单独抽离出来了,如下图

image-20200715164924441.png

四、在 el-table 表格中使用 radio 单选按钮

项目需求如下图:
image-20200715165551519.png

然后要将选中数据 id 传递给后端 。具体代码如下:

<el-table>
     <el-table-column label="选择">
         <template slot-scope="scope">
              <el-radio v-model="radioStatus" :label="scope.$index" 
          @change.native="getRowSelected(scope.$index, scope.row)"
                  > &nbsp; </el-radio>
        </template>
    </el-table-column>
    ... ...
</el-table>

export defalut {
    data() {
        return {
            radioStatus: false, // 是否被选中,默认都是 false
            selectedId: '' //选中数据的id
        }
    },
    methods: {
        // 获取选中数据
        getRowSelected(index, row) {
            this.selectedId = row.id 
        }
    }
}

注意:radio 的 label 一定要设为不同的值,否则点击一个 radio 会选中全部。如果不要显示 label,通过样式控制其隐藏就可以了。

五、el-table 改变单元格某一列的样式

表格中某一列的数值根据不同等级展示不同的背景色。具体需求如下:

image-20200716105733669.png

通过table的cell-style属性,可以设置一个固定的 Object 或 Function({row, column, rowIndex, columnIndex}),这里用了回调的方法。实现代码如下:

<el-table :data="tableData" style="width: 100%" border :cell-style="set_cell_style">
     <el-table-column label="选择">
         ... ...
    </el-table-column>
</el-table>

... ...
methods: {
    set_cell_style({row, column, rowIndex, columnIndex}) {
        if(row.errorNum > 20 && column.label === '检测错误数') {
            return {  // 返回对象
                background: '#F56C6C', color: 'white'
            }
        } else if(row.errorNum > 10 && column.label === '检测错误数') {
            return {
                  background: '#E6A23C', color: 'white'
            }
        } else if(row.errorNum > 0 && column.label === '检测错误数') {
            return 'background: #67C23A; color: white' // 返回字符串
        }
    }
}
// row 行数据对象  column 列对象
// 上述 column.label === '检测错误数' 等价于 columnIndex === 4
// 用label主要是以免表格展示顺序更换,columnIndex也得相应的更改

注意:使用 function 时 return 的返回值如果是 string 类型,在开发环境是可以生效的,但是打包上线后失效。所以如果使用 function,要返回 object 类型

六、el-table 动态生成表头

el-table 根据后端返回的数据,动态生成表头并展示相应的值。如后端返回的数据如下:

image

要求显示如下:
image
其中 name, id, salary 用于表头的label显示,并通过prop绑定这些数据的值。具体实现如下:

// 处理后端返回的数据data,并定义ruleTableLabel存储label
data.map(item => {
    Object.keys(item).map(key => {
        !this.ruleTableLabel.includes(key) && this.ruleTableLabel.push(key)
    })
})

// 循环并绑定prop
<el-table-column v-for="(key, i) in ruleTableLabel" :key="i" :label="key" :prop="key"></el-table-column>

七、el-table列使用fixed属性后,与其他列出现错位

具体错误如下图所示:
image

其中操作列设置了固定,初始展示列表页时没啥问题,但是从详情页返回时就出现了这样一个错位,用了doLayout方法也不行。然后把样式 el-table__fixed-body-wrapper 的top值修改成表头的高度就可以了。

image

八、el-table-column 添加 show-overflow-tooltip 的内容超长,鼠标放上去后一直闪烁

这里主要是显示后端返回的日志信息,但是因为这个数据比较多,而且使用 show-overflow-tooltip 的列文本内容超长,最小的也有10+kb,然后鼠标放上去的时候就一直闪动,完整的内容也显示不出来。具体问题如下图:

image

然后用了 el-tooltip 代替 show-overflow-tooltip 这个属性,具体代码如下:

<el-table-column prop="logMsg" label="日志信息" show-overflow-tooltip align="center">
    <template slot-scope="scope">
        <el-tooltip effect="light" :content="scope.row.logMsg" popper-class="log-tooltip" :disabled="scope.row.logMsg | ellipsis" placement="top">
            <span v-if="scope.row.logMsg.length > 100">{{ scope.row.logMsg.split(0, 100)[0] + '...' }}</span>
            <span v-else>{{ scope.row.logMsg }}</span>
        </el-tooltip>
    </template>
</el-table-column>

添加过滤器和样式:

//添加过滤器
filters: {
    //如果文本内容长度少于100,就不显示tooltip组件
    ellipsis (value) {
        if (value.length > 100) {
            return false
          }
          return true
    }
}

//并给tooltip组件添加样式
.log-tooltip.el-tooltip__popper{
    max-width: 90%;
    height: 90%;
    left: 5%;
    right: 5%;
    top: 5%;
    bottom: 5%;
    margin: 0 auto;
    overflow: scroll;
}

注意:el-tooltip__popper的样式如果添加在scoped中是不生效的,因为元素默认是追加在body的。通过popper-class属性对样式进行限定,否则其他页面有用到el-tooltip的样式会被覆盖。

九、el-table 带翻页的全选

在使用 element-ui 的 el-table 组件展示数据时,有时会要求批量提交不同页面勾选数据的功能,当切换分页时,能够记忆所有页面勾选的数据,然后进行批量操作。官网也没有直接提供案例来实现这种业务需求,但可以通过设置row-key、reserve-selection和selection-change事件来实现。

  • reserve-selection:仅对 type=selection 的列有效,类型为 Boolean,为 true 则会在数据更新之后保留之前选中的数据。
  • row-key:行数据的 Key,用来优化 Table 的渲染;在使用 reserve-selection 功能与显示树形数据时,该属性是必填的。主要用来表示每行数据是通过哪个属性来进行区分,一般使用id。
  • selection-change:当选择项发生变化时会触发该事件。参数 selection 将是所有页面已经勾选的数据。
<template>
    <el-card>
        <el-table :table-loading="loading"
            :tableData="tableData"
            ref="tableRef"
            :row-keys="getRowKeys"
            @selectionChange="selectionChange">
            <el-table-column :reserve-selection="true" type="selection" width="55" />
            ... ...
        </el-table>
        <com-pagination
            :current-page="currentPage"
            :page-sizes="pageSizes"
            :page-size="pageSize"
            :total="total"
            @handleSizeChange="handleSizeChange"
            @handleCurrentChange="handleCurrentChange" />
    </el-card>
</template>

<script>
    export default {
        name: 'index',
        data() {
            return {
                tableData: [], // 表格数据
                pageSizes: [20, 50, 100],
                total: 0,
                pageSize: 20,
                currentPage: 1,
                loading: false,
                multipleSelectionIds: [], // 所有选中的数据id集合包含跨分页数据
                getRowKeys(row) { // 获取row的key值,并返回row.id为每行记录的唯一标识
                    return row.id
                }
            }
        },
        computed: {
            // 请求数据列表的参数
            queryParams() {
                return {
                    //...其他参数,
                    page: this.currentPage,
                    limit: this.pageSize
                }
            }
        },
        mounted() {
            this.queryList()
        },
        methods: {
            queryList() {
                // 调用后端接口,获取table表格数据
                ......
            },
            // 选中事件:单选或单页全选
            selectionChange(selection) {
                this.multipleSelectionIds = selection.map(item => item.id)
            },
            // 切换页码
            handleSizeChange(val) {
                this.pageSize = val
                this.queryList()
            },
            // 翻页
            handleCurrentChange(val) {
                this.currentPage = val
                this.queryList()
            }
        }
    }
</script>

如果是所有数据的全选,添加一个全选的按钮,在传参的时候跟后端约定一个全选的标识,因为添加了分页功能,默认只能从接口获取到一页的数据而不是所有的,通过约定的全选标识让后端处理所有数据的全选。页面展示的数据是否选中,只需要监听一下tableData的数据变化,然后通过 this.$refs.table.toggleRowSelection(row, true) 来设置行的选中状态就可以了。

十、el-table 中 type=selection 的列自定义label文字

  • 使用表格属性:header-cell-class-name,为单元格设置className,然后自定义样式
<el-table :data="tableData" ref="table" :header-cell-class-name="cellclass" style="width: 100%"/>
    ... ...
</el-table>          

methods: {
    cellclass(row){
        if(row.columnIndex === 0){
            return 'table-selection'
        }
    }
}
  • 使用属性 label-class-name 给当前列自定义className和样式
<el-table-column label-class-name="table-selection" type="selection"></el-table-column>

以上这两种方法的样式修改如下:

<style lang="less" scoped>
    .el-table /deep/.table-selection .cell .el-checkbox__input{
        display:none;
    }
    .el-table /deep/.table-selection .cell:before{
        content: "选择";
        position: relative;
    }
</style>
  • 直接修改el-table selection的默认样式
<style lang="less" scoped>
    .el-table__header .el-table-column--selection .cell .el-checkbox {
        display:none;
    }
    .el-table__header .el-table-column--selection .cell:before {
        content: "选择";
    }
</style>
  • 重写selection列
<el-table :data="tableData" style="width: 100%">
    <el-table-column label="选择" width="50">
        <template slot-scope="scope">
            <el-checkbox></el-checkbox>
        </template>
    </el-table-column>
</el-table>

十一、el-table 数据的简单筛选过滤

一般涉及到 table 表格数据的筛选过滤,都是通过调用后端接口来完成的。

在之前的项目中,有几个页面的列表数据,筛选条件只有一个,后端懒得加,就只好自己弄了一个简单的过滤展示。具体如下:

//this.name过滤条件  tableData列表数据
<el--table :table-loading="loading" ref="table" 
    :tableData="tableData.filter(d => d.name.indexOf(this.name) > -1)">
</el-table>

这种方法如果筛选条件多了就不行了,还是得需要后端处理


sugar_coffee
455 声望19 粉丝