el-table固定列的hover无效果?

262 阅读2分钟

关于el-table中的固定列,在el-table-column存在el-popover显示其他表格时出现行hover效果错位问题。 问题详情可查看issue

问题复现

<template>
  <el-table :data="tableData" border style="width: 100%">
    <el-table-column fixed prop="date" label="日期" width="300">
    </el-table-column>
    <el-table-column prop="name" label="姓名" width="50">
    </el-table-column>
    <el-table-column prop="province" label="弹出层表格" width="180">
      <template>
        <el-popover placement="right" trigger="hover" width="400">
          <el-table :data="gridData">
            <el-table-column width="150" property="date" label="日期"></el-table-column>
            <el-table-column width="100" property="name" label="姓名"></el-table-column>
            <el-table-column width="300" property="address" label="地址"></el-table-column>
          </el-table>
          <el-button slot="reference">弹出层表格</el-button>
        </el-popover>
      </template>
    </el-table-column>
    <el-table-column prop="province" label="省份" width="250">
    </el-table-column>
    <el-table-column prop="city" label="市区" width="150">
    </el-table-column>
    <el-table-column prop="address" label="地址" min-width="450">
    </el-table-column>
    <el-table-column prop="zip" label="邮编" width="220">
    </el-table-column>
    <el-table-column fixed="right" label="操作" width="180">
      <template slot-scope="scope">
        <el-button @click="handleClick(scope.row)" type="text" size="small">
          查看
        </el-button>
        <el-button type="text" size="small">编辑</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>
<script >
export default {
  data() {
    return {
      tableData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          province: "上海",
          city: "普陀区",
          address: "上海市普陀区金沙江路 1518 弄",
          zip: 200333
        },
        {
          date: "2016-05-04",
          name: "王小虎",
          province: "上海",
          city: "普陀区",
          address: "上海市普陀区金沙江路 1517 弄",
          zip: 200333
        },
        {
          date: "2016-05-01",
          name: "王小虎",
          province: "上海",
          city: "普陀区",
          address: "上海市普陀区金沙江路 1519 弄",
          zip: 200333
        },
        {
          date: "2016-05-03",
          name: "王小虎",
          province: "上海",
          city: "普陀区",
          address: "上海市普陀区金沙江路 1516 弄",
          zip: 200333
        }
      ],
      gridData: [
        {
          date: "2016-05-02",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄"
        },
        {
          date: "2016-05-04",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄"
        },
        {
          date: "2016-05-01",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄"
        },
        {
          date: "2016-05-03",
          name: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄"
        }
      ]
    };
  },
  methods: {
    handleClick(row) {
      console.log(row);
    }
  }
}
</script>

1718334653245.jpg

1718335899945.jpg

在上述代码中,当弹出层弹出后,可以明显看出表格每一行在鼠标划过的时候固定列的hover效果明显错位或者丢失。 这是由于el-table在处理hover效果时使用了this.$el.querySelectorAll('.el-table__row')来查找元素, 源码packages/table/src/table-body.js第95行。

1718335799636.jpg 1718334967069.jpg

在打开控制查看存在el-popover的列时,发现el-popover包裹的表格已经渲染到el-table-column里,在el-popover 弹出时,el-table-columnel-table__row元素被移除到body,所以在this.$el.querySelectorAll('.el-table__row') 的时候查找到的el-table__row变多,导致实际出现hover效果的el-table__row节点不是外层表格el-table__row节点。

解决方案

解决方案可通过二次封装el-popover来现实,主要方案是初始化不渲染el-popover包裹的表格,在显示的时候才去渲染。

<script>
export default {
  name: 'MyElPopover',
  data() {
    return {
      isRender: false
    }
  },
  render() {
    const _vm = this
    const _h = _vm.$createElement
    const _c = _vm._self._c || _h
    return _c('el-popover', _vm._g(_vm._b({
      on: {
        'show': _vm.popoverShow,
        'after-leave': _vm.popoverHide
      }
    }, 'el-popover', _vm.$attrs, false), _vm.$listeners), [(_vm.isRender) ? _c(
      'div', {
        staticClass: 'my-popover_content'
      }, [_vm._t('default')], 2) : _vm._e(), _vm._t('reference', null, {
      'slot': 'reference'
    })], 2)
  },
  methods: {
    popoverShow() {
      // 显示时渲染
      this.isRender = true
      this.$emit('show')
    },
    popoverHide() {
      // 隐藏时移除渲染
      this.isRender = false
      this.$emit('after-leave')
    }
  }
}
</script>

my-el-popover的事件属性跟原生el-popover一致,使用方法也一致。完美解决。