a-table表格

1,921 阅读4分钟

"ant-design-vue": "^1.78"

table表格customRender的使用

使用customRender指定渲染内容

colums: [
    {
        title: '类型',
        dataIndex: 'type',
        customRender: (text, record) => {
            console.log(record);
            if (text === 0) {
                return '客户1'
            } else if (text === 1) {
                return '客户2',
            } else if (text === 2) {
                return '客户3'
            }
        }
    }
]

注意:text参数为当前行的值;record参数为当前行数据

使用customRender引入插槽

scopedSlots: { customRender: 'action' }

在slot中使用 a-tooltip(文字提示)

插槽代码。文本溢出显示省略号。

<template slot="tooltipSlot" slot-scope="text">
                    <a-tooltip placement="top" :title="text">
                        <div
                            style="width: 350px; overflow: hidden; text-overflow: ellipsis"
                        >{{ text }}</div>
                    </a-tooltip>
                </template>

需要注意的是需要设置宽度,否则不能实现居中

{
            title: '诉求内容',
            align: "center",
            width: 350, // 对于tooltipSlot需要设置宽度才能居中
            dataIndex: 'sjms',
            scopedSlots: { customRender: 'tooltipSlot' }

        },

"ant-design-vue": "^3.2.20"

customRow设置行属性Function(record, index)

鼠标右键事件和关闭事件,双击事件

const customRow = (record, index) => {
  return {
    // 鼠标右键
    onContextmenu: (e) => {
      e.preventDefault();
      document.body.addEventListener("click", cancelClick);
    },
    // 鼠标双击
    ondblclick: (e) => {
    },
  };
};

cancelClick关闭事件

const cancelClick = () => {
    document.body.removeEventListener("click", cancelClick);
};

拖拽事件

拖拽分为同表格拖拽和跨表格拖拽。官网推荐的Surely Table不付费会有水印,且需要导入新的组件库,功能也不完善。官网中所给出的案例只支持同表格拖拽、单行拖拽。

copy网上案例、加工实现多行跨表格移动、单行同表格排序

拖拽的数据定义在pinia中,src/store/draggable.js

import {
    defineStore
} from 'pinia'

export const draggableRecord = defineStore('draggableRecord', {
    state: () => {
        return {
            record: [],
            source: ''
        }
    },
    actions: {
        init() {
            this.record = []
            this.source = ''
        },
        draggable(record, source) {
            this.record = record
            this.source = source
        }
    },
})

表格组件 videoList.vue

    <a-table
      :columns="columns"
      :data-source="data"
      :pagination="false"
      :row-selection="rowSelection"
      :customRow="customRow"
    >
<script setup>

import { draggableRecord } from "/@/store/draggable";
const props = defineProps({
  // 组件渲染位置 top: 视频列表, import: 导入视频列表
  which: {
    type: String,
    default: "top",
    required: true,
  }
})
const emit = defineEmits(["diff-source", "same-source"]);
const draggableStore = draggableRecord();

let change1 = null; // 源数据序号
let change2 = null; // 目标数据序号
const customRow = (record, index) => {
  return {
    // 拖拽------------------------------------------------start
    onMouseenter: (event) => {
      // 兼容IE
      var ev = event || window.event;
      ev.target.draggable = true; // 让你要拖动的行可以拖动,默认不可以
    },
    // 开始拖拽
    onDragstart: (event) => {
      // 兼容IE
      var ev = event || window.event;
      // 阻止冒泡
      ev.stopPropagation();
      // 得到源目标数据序号
      change1 = index;
      // 判断是否为多选拖拽
      Object.keys(rowSelect.value).length > 0
        ? draggableStore.draggable(rowSelect.value, props.which)
        : draggableStore.draggable([record], props.which);
      // console.log(record, index, "上面source");
    },
    // 拖动元素经过的元素
    onDragover: (event) => {
      // 兼容 IE
      var ev = event || window.event;
      // 阻止默认行为
      ev.preventDefault();
    },
    // 鼠标松开
    onDrop: (event) => {
      // 兼容IE
      var ev = event || window.event;
      // 阻止冒泡
      ev.stopPropagation();
      // 得到目标数据序号
      change2 = index;
      // 根据数据来源和当前位置,计算是跨表格还是本表格
      draggableStore.source === props.which
        ? rowSelect.value.length > 0 // 多选不支持排序
          ? ""
          : emit("same-source", {
              change1,
              change2,
            })
        : emit("diff-source", { index, record: draggableStore.record });
      // console.log(data, index, "上面的target");
      draggableStore.init(); // 将拖拽数据初始化
    },
    // 拖拽------------------------------------------------end
  };
};
</script>

父组件importVideo.vue

    <video-list
      which="import"
      :data="importData"
      :columns="videoColums"
      @same-source="onSameSource"
      @diff-source="onDiffSource"
    ></video-list>
 <script setup>
 const onDiffSource = (mess) => {
  // console.log("onDiffSource");
  importData.splice(mess.index, 0, ...mess.record);
};
const onSameSource = (mess) => {
  // console.log("onSameSource");

  const move = importData[mess.change1];
  importData.splice(mess.change1, 1);
  importData.splice(mess.change2, 0, move);
};
</script>

getPopupContainer解决悬浮窗遮挡问题

ant.design/components/… 给出的定义

弹出框(Select, Tooltip, Menu 等等)渲染父节点,默认渲染到 body 上。

如果你使用的 a-select、a-popover、a-tooltip、a-menu等组件都可以直接使用此属性

  <a-select
    v-model="title"
    show-search
    :options="filterList"
    :getPopupContainer="getPopupContainer"
  ></a-select>
  
  //js
  // 解决antdv组件被覆盖的问题
    const getPopupContainer = (node) => {
        return document.body
    };

效果为:

getPopupContainer改变渲染节点.jpg

官网给出的写法:

getPopupContainer={triggerNode => triggerNode.parentElement || document.body}

有些场景无法解决问题,见下【customHeaderCell设置头部单元格属性,Select】

customHeaderCell设置头部单元格属性,Select

如果是分页的话,参照官网案例【自定义筛选菜单】章节

但是如果是滚动形式就会出现一些bug

 <a-table
      class="ant-table-striped"
      :columns="columns"
      :data-source="data"
      :pagination="false"
      :scroll="{x:1000, y:410}"
    >
      <template #headerCell="{title, column }">
            <a-select
              v-model="column.title"
              show-search
              :placeholder="title"
              :style="{width: column.filterType === 'select' ? '100%': '70%'}"
              :options="filterList[title]"
              :filter-option="filterOption"
              :getPopupContainer="getPopupContainer"
            ></a-select>
      </template>
    </a-table>

bug

table-header溢出隐藏.jpg

当设置 :scroll="{x:1000, y:410}"属性后,ant-table-header就会添加overflow: hidden;,影响下拉等悬浮层的显示

如果使用css的方式解决问题,表头横向就无法实现滚动,而是溢出显示。

:deep(.ant-table-header) {
	overflow: visible
}

并且不能这样写:

:deep(.ant-table-header) {
	overflow-y: visible;
	overflow-x: hidden;
}

overflow-x和overflow-y设置冲突问题

只能使用getPopupContainer

不能使用官网给出的return triggerNode.parentElement,这个return不能解决这个问题

    const getPopupContainer = (node) => {
        return document.body
    };

ant-table-body添加滚轮事件

直接给 a-table 使用 ref 无法获取dom,所以在外层添加父元素

  <div ref="ant_table_box" class="table-box" :class="scrollHidden ? 'no-srcoll-y': ''">
    <a-table
      class="ant-table-striped"
      :columns="columns"
      :data-source="data"
      :pagination="false"
      :scroll="tableProps.scroll"
      :customRow="customRow"
    >
  </div>
  
// js
const tableProps = reactive({
  scroll: {
    x: 988,
    y: 410,
  },
});
const ant_table_box = ref(null);
  });
const scrollHidden = computed(() => {
  if (ant_table_box.value != null) {
    const ant_table_body_dom =
      ant_table_box.value.querySelector(".ant-table-body");
    if (ant_table_body_dom.offsetHeight > tableProps.scroll.y) {
      return false;
    } else {
      return true;
    }
  } else {
    return false;
  }
});
onMounted(() => {
  if (ant_table_box.value) {
    const ant_table_body_dom =
      ant_table_box.value.querySelector(".ant-table-body");
    ant_table_body_dom?.addEventListener("scroll", (event) => {
      // 计算滚动到底部的条件
      // -1 防止误差
      const isBottom =
        ant_table_body_dom.clientHeight +
          parseInt(ant_table_body_dom.scrollTop.toFixed(0)) ===
          ant_table_body_dom.scrollHeight ||
        ant_table_body_dom.clientHeight +
          parseInt(ant_table_body_dom.scrollTop.toFixed(0)) -
          1 ===
          ant_table_body_dom.scrollHeight;
      if (isBottom) {
        // 滚动到底部时执行你的逻辑
        const newData = Object.assign([], props.data.slice(0, 10));
        props.data.push(...newData);
        // console.log("改变后的table数据", props.data);
      }
    });
  }
});

// css
<style scoped lang="less">
  :deep(.ant-table-body) {
    &::-webkit-scrollbar {
      border-radius: 5px;
      height: 8px;
      width: 5px;
      background-color: #a09d9d;
    }

    &::-webkit-scrollbar-thumb {
      width: 10px;
      border-radius: 10px;
      // background-color: rgba(192, 39, 39, 0);
      background: #24222294;
    }
  }
.no-srcoll-y {
  :deep(.ant-table-body) {
    overflow: auto !important;
  }
}
.table-box {
    width: 100%;
    position: relative;
    border-radius: 4px;
    border: 1px solid rgb(63, 61, 61);
    overflow: hidden;
}
</style>