【源码分析系列】antdv table滚动时固定表头

news2024/11/24 0:33:09

背景

当页面滚动的时候,如果超过表格的部分,表格的头部会固定在某个位置,方便用户看到数据栏的标。项目采用的是vue2+antdv,但是这个版本的table没有sticky属性,所以需要自行解决。
滚动前:
在这里插入图片描述
滚动后:
在这里插入图片描述

原理

知道大概是用了sticky属性,但是奈何我在怎么修改元素的style还是没有起到想要的作用,经过多番寻找,找到了这样一个问题:Table header sticky feature,在这最后有一个老哥提到了自己封装的一个指令:antd-table-sticky.js。

所以研究一下它的基本实现原理,在antdv table中,它的页面结构是这样的:

div.ant-table
  div.ant-table-content
    div.ant-table-scroll
      div.ant-table-body
        table.ant-table-fixed
          colgroup
          thead.ant-table-thead
          tbody.ant-table-tbody
          

之前我以为是在ant-table-content上或者是内部的html中加入关于sticky的属性,然而通过测试,大佬的方法主要是复制了一个.ant-table-content元素,放在同级,将其设置fixed

div.ant-table-content
    div.ant-table-scroll
      div.ant-table-body
        table.ant-table-fixed
          colgroup
          thead.ant-table-thead
          tbody.ant-table-tbody

然后修改这个ant-table-content的样式,并当作兄弟组件插入,最后的结果是这样的:

div.ant-table
  div.ant-table-content
  div.ant-table-content(position: fixed; top: 64px; z-index: 1000; background-color: rgb(255, 255, 255); width: 1114px;)

如图所示:
在这里插入图片描述
实现的过程大概是这样的:

  • 获取滚动容器,支持id传入获取指定的容器,不然就是默认window
  • 深度拷贝ant-table-content节点,并将这个节点设置样式:position: fixed;top: ${fixedTop}px; z-index: ${zIndex}; ${stickyStyle.cssText};background-color: ${bgColor}
  • 监听:
    • 监听容器滚动,如果滚动到指定位置,就插入拷贝的节点,否则就移除;
    • 监听容器的大小,要重置拷贝节点的宽度;
    • 监听.ant-table-body的滚动,设置拷贝节点的横向位置
  • 当表格发生更新的时候,移除.ant-table-tbody,.ant-table-placeholder,这样就只有表头了

源码

/**
 * 使Ant Design Vue的Table组件支持表头sticky
 * 单元格宽度必须固定
 */
import { throttle } from 'lodash'

let listenAction;
let container;
let stickyHeader = null;
let originEl = null;
let bindingConfig = {};

const originSelector = '.ant-table-content';
const scrollSelector = '.ant-table-scroll .ant-table-body';
const toRemoveSelector = '.ant-table-tbody,.ant-table-placeholder';

// 获取指令参数
const getBindingConfig = (binding) => {
  const params = binding.value || {};
  const {
    fixedTop = 64,
    zIndex = 1000,
    bgColor = '#fff',
    disabled,
    scrollContainerId
  } = params;
  return { fixedTop, zIndex, disabled, scrollContainerId, bgColor };
};

const unwatch = () => {
  container && container.removeEventListener('scroll', listenAction);
  container && container.removeEventListener('resize', resizeStickyHeader);
  originEl && originEl.querySelector(scrollSelector).removeEventListener('scroll', setScrollX);
};

const watch = () => {
  container && container.addEventListener('scroll', listenAction);
  container && container.addEventListener('resize', resizeStickyHeader);
  originEl && originEl.querySelector(scrollSelector).addEventListener('scroll', setScrollX);
};

// 根据表格实际内容修改表头内容
const adaptStickyHeader = () => {
  stickyHeader.innerHTML = originEl.innerHTML;
  stickyHeader.querySelector(scrollSelector).style.overflowX = 'hidden';
  const tbodyList = Array.from(stickyHeader.querySelectorAll(toRemoveSelector));
  tbodyList.forEach((tbody) => {
    tbody.parentNode.removeChild(tbody);
  });
  resizeStickyHeader();
  setScrollX();
};

// 根据实际内容设置宽度
const resizeStickyHeader = throttle(() => {
  stickyHeader.style.width = `${originEl.getBoundingClientRect().width}px`;
});

// 根据表格横向滚动,设置表头的横向位置
const setScrollX = throttle(() => {
  const stickyHeaderScroller = stickyHeader.querySelector(scrollSelector);
  const originScroller = originEl.querySelector(scrollSelector);
  stickyHeaderScroller.scrollLeft = originScroller.scrollLeft;
});

export default {
  bind(el, binding) {
    // 获取 .ant-table-content
    originEl = el.querySelector(originSelector);
    // 读取指令参数
    bindingConfig = getBindingConfig(binding);

    const { disabled, fixedTop, zIndex, scrollContainerId, bgColor } = bindingConfig;

    if (disabled) return;

    // 如果没有指定父级容器的id,则默认为浏览器
    container = document.getElementById(scrollContainerId) || window;
    let active = false;
    stickyHeader = originEl.cloneNode(true);
    const stickyStyle = stickyHeader.style;
    stickyStyle.cssText = `position: fixed;top: ${fixedTop}px; z-index: ${zIndex}; ${stickyStyle.cssText};background-color: ${bgColor}`;

    const sticky = () => {
      if (active) return;
      setScrollX();
      originEl.insertAdjacentElement('afterend', stickyHeader);
      active = true;
    };

    const reset = () => {
      if (!active) return;
      stickyHeader.parentNode?.removeChild(stickyHeader);
      active = false;
    };

    listenAction = throttle(() => {
      const rectEl = originEl?.parentNode;
      const rect = rectEl.getBoundingClientRect();
      const offsetTop = rect.top;
      if (offsetTop <= fixedTop) {
        return sticky();
      }
      reset();
    });

    watch();
  },

  unbind: unwatch,

  update(el, binding) {
    bindingConfig = getBindingConfig(binding);
    originEl = el.querySelector(originSelector);

    if (bindingConfig.disabled) {
      stickyHeader.parentNode?.removeChild(stickyHeader);
      unwatch();
      return;
    }

    adaptStickyHeader();
  },
};

参考

  • Table header sticky feature
  • antd-table-sticky.js

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1161968.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WoShop多语言外贸跨境商城源码(支持直接铺货,多语言,多货币切换)

多语言外贸跨境商城源码是一种用于构建多语言跨境电子商务平台的软件解决方案。这种源码通常支持多种语言&#xff0c;以便让商家能够轻松地将他们的产品和服务销售到全球各地。 以下是多语言外贸跨境商城源码的一些主要特点&#xff1a; 1. 多语言支持&#xff1a;源码通常支持…

类百度知识付费网站

需购买&#xff1a;部署联系&#xff0c;支持压缩包&#xff0c;doc&#xff0c;pdf预览等

什么?前端又出新轮子了?ofa.js

不需要打包的 MVVM JavaScript 框架 无需繁琐学习&#xff0c;无需 npm、nodejs、webpack&#xff0c;即刻上手 <script src"https://cdn.jsdelivr.net/gh/kirakiray/ofa.js/dist/ofa.min.js"></script>官方文档 取代 jQuery 在许多小型项目中&#x…

研发效能DevOps: Git安装

目录 一、理论 1.Git 2.Git 工具 二、实验 1.Git安装 2.配置Git 3. VS Code加载Git 一、理论 1.Git &#xff08;1&#xff09;简介 Git 是一个分布式版本控制及源代码管理工具;Git 可以为你的项目保存若干快照&#xff0c;以此来对整个项目进行版本管理。 Git 是一个…

clusterprolifer go kegg msigdbr 富集分析应该使用哪个数据集,GO?KEGG?Hallmark?

关注微信&#xff1a;生信小博士 5 Overview of enrichment analysis Chapter 5 Overview of enrichment analysis | Biomedical Knowledge Mining using GOSemSim and clusterProfiler 5.1.2 Gene Ontology (GO) Gene Ontology defines concepts/classes used to describ…

毕业生求职,需要做哪些准备工作?

第一、了解企业招聘需求&#xff0c;不同岗位除了对应的专业知识以为&#xff0c;还需要了解岗位的特点&#xff0c;比如&#xff1a;销售类型的工作&#xff0c;口才要好&#xff0c;逻辑要强。如果你懂技术&#xff0c;但是羞于表达&#xff0c;都是无法胜任的。结合自身性格…

ztree调整节点间距及一般使用

1.基本介绍 树形结构菜单的功能属于非常常见的一种菜单交互&#xff0c;本人先后也使用过多种树形结构的插件&#xff0c;有 ztree、xloadtree、treeview、datagrid-tree 等等等等。近期有个功能恰好又要使用tree菜单了&#xff0c;由于可自行选择使用的组件&#xff0c;所以略…

简单工厂模式、工厂方法模式、抽象工厂模式

简介 将实例化代码提取出来&#xff0c;放到一个类中统一管理和维护&#xff0c;达到和主项目依赖关系的解耦&#xff0c;从而提高项目的扩展性和维护性。 工厂模式将复杂的对象创建工作隐藏起来&#xff0c;而仅仅暴露出一个接口供客户使用&#xff0c;具体的创建工作由工厂管…

Axie Infinity 超级任务远超预期,和 YGG 一起探索 Web3 增长新方式!

参与超级任务的实际人数是预期人数的两倍。 超级任务将新玩家引入 Web3 游戏领域&#xff0c;并向他们介绍可以为其玩家旅程提供支持的社区。 Axie Infinity 超级任务旨在向新手和 Axie Classic 老 玩家介绍「Axie Infinity&#xff5c;起源」这款游戏。 整个活动共吸引了 4,…

Luminar Neo Mac/Windows中文版:引领AI图像编辑的革命性时代

Luminar Neo运用先进的AI技术&#xff0c;能够自动化地完成许多繁琐的编辑任务&#xff0c;如色彩校正、噪点消除、人脸识别等。这不仅大大提高了工作效率&#xff0c;同时也降低了对专业知识和技能的要求。无论你是专业摄影师&#xff0c;还是摄影爱好者&#xff0c;甚至是一个…

python写爱心代码【爱心代码编程python可复制粘贴】

python写爱心代码【爱心代码编程python可复制粘贴】 python程序代码&#xff1a;heart.py from math import cos, pi import numpy as np import cv2 import os, glob class HeartSignal: def __init__(self, curve"heart", title"Love U", frame_n…

程序员用接单平台靠谱吗?浅谈一下十年程序员的看法

后疫情时代&#xff0c;经济下行&#xff0c;这年头社会上就业也越来越卷了&#xff0c;程序员人才市场也日趋饱和。不少人嗅到危险气息&#xff0c;已经开始谋求出路了! 咱们程序员的话&#xff0c;“兼职”"接单"也不是个新鲜的话题了。养家糊口也好、财富自由也罢…

优优嗨聚集团:医保新政来袭,乙类OTC、保健品或将退出医保舞台,影响几何?

近日&#xff0c;国家医保局发布征求意见稿&#xff0c;拟将乙类OTC&#xff08;非处方药&#xff09;和保健品从医保目录中移除。这一政策一旦实施&#xff0c;无疑将对广大参保人员和相关企业产生深远影响。本文将为您详细解析这一政策可能带来的影响&#xff0c;以及如何应对…

19.3 Boost Asio 多线程通信

多线程服务依赖于两个通用函数&#xff0c;首先boost::bind提供了一个高效的、简单的方法来创建函数对象和函数对象适配器&#xff0c;它的主要功能是提供了一种将函数和它的参数绑定到一起的方法&#xff0c;这种方法可以将具有参数的成员函数、普通函数以及函数对象转化为不带…

日常笔记工具搭档(Typora、Snipaste)

一、Typora 啥也不说了直接上图 Markdown语法 Typora免费版 提取码&#xff1a;av01 二维码&#xff1a; 1&#xff09;页面展示 2&#xff09;主题 3&#xff09;偏好设置 4&#xff09;Markdown语法设置偏好 5&#xff09;编辑器 6&#xff09;系统 二、Snipaste Snipaste…

中国电子云-隐私计算-云原生安全可信计算,物理-硬件-系统-云产品-云平台,数据安全防护

目录 联邦学习的架构思想 中国电子云-隐私计算-云原生安全 可信计算&#xff0c;物理-硬件-系统-云产品-云平台&#xff0c;数据安全防护 全栈国产信创的意义 1. 提升科技创新能力 2. 推动经济发展 3. 加强信息安全与自主可控 全栈国产信创的重要领域 1. 人工智能 2.…

Nginx简介,Nginx搭载负载均衡以及Nginx部署前端项目

目录 一. Nginx简介 Nginx的优点 二. Nginx搭载负载均衡 2.1 Nginx安装 2.1.1 安装依赖 2.1.2 解压nginx安装包 2.1.3 安装nginx 2.1.4 启动nginx服务 2.2 tomcat负载均衡 2.3 Nginx配置 三. Nginx前端部署 一. Nginx简介 NGINX&#xff08;读作&#xff1a;engi…

阿里云2023年双十一活动各云产品活动内容及优惠政策汇总

阿里云2023双十一活动各云产品有哪些新购和续费优惠政策&#xff1f;小编看了一下阿里云2023年的双十一活动&#xff0c;活动分为主会场和8个云产品分会场&#xff0c;涉及的云产品涵盖了云服务器、云数据库、云存储、云网络、大数据Al、云原生、云安全等几乎所有阿里云产品&am…

技能get-ps抠颜色一样的图

公司要插个小图片&#xff0c;从网上down下来的图片是不过是jpg的&#xff0c;背景不透明&#xff0c;这时候可以使用ps工具把这种同一颜色的内容扣下来。 操作步骤&#xff1a; 选择-色彩范围&#xff0c;然后用取样器取颜色&#xff0c;再调节拉条选取颜色范围&#xff0c;最…

客户收到样品后“消失”,怎么破?

对于大部分外贸人来说&#xff0c;谈客户几乎不是一次性谈成的&#xff0c;而是要进行多次的沟通。在沟通过程中难免会遇到各种问题&#xff0c;一些小问题容易解决&#xff0c;但有一些棘手的问题却不知该如何下手。 比如&#xff1a; ①客户收到样品后就“消失”&#xff0c…