【无标题】vue2 + element-ui 表格无固定高度相对于指定父元素进行表头吸顶

网上找过很多表格吸顶类的都不太如意,自己动手封装一个。啥都不说了直接上vue代码:
1.主页代码:(主要是弹框,组件的地址根据自己copy的位置自行修改)

<template>
    <div class='mainPage'>
        <el-button type="primary" size="mini" @click="openDig">主要按钮</el-button>
        <el-dialog
            title="提示"
            :visible.sync="dialogVisible"
            width="80%"
            :before-close="handleClose">
            <div class="rowBox">21321321</div>
            <tabCom 
                :stickyClass="'el-dialog__body'"
                :isSticky="true"
            />
        </el-dialog>
    </div>
</template>

<script>
import tabCom from "../components/tabCom.vue"
export default {
    components: {
        tabCom,
    },
    data() {
        return {
            dialogVisible:false
        };
    },
    computed: {},
    watch: {},
    created() {},
    mounted() {},
    methods: {
        openDig(){
            this.dialogVisible = true
        },
        handleClose(){
            this.dialogVisible = false
        },
    },//methods End
}
</script>
<style lang='less' scoped>
/*@import url(); 引入公共css类 */
.rowBox{
    width: 100%;
    height: 50px;
    display: flex;
    background: red;
}
</style>

2:tabCom 组件内代码:

<template>
  <div :class="stickyClassKey">
    <div class="stickyFixed">
      <div class="stickyFixedContentBox">
        <div
          class="fixedLeftHeader"
          :class="showShadow? 'leftShadow': ''"
        ></div>
        <div class="stickyFixedMainBox"></div>
        <div
          class="fixedRightHeader"
          :class="showShadow? 'rightShadow': ''"
        ></div>
      </div>
    </div>
    <el-table
      :data="tableData"
      border
      :class="'isStickyTab'"
      style="width: 100%"
    >
      <el-table-column type="selection" width="55"></el-table-column>
      <el-table-column prop="date" label="日期" fixed="left" width="180"></el-table-column>
      <el-table-column prop="name" label="姓名" width="180"></el-table-column>
      <el-table-column prop="address" width="200" label="地址"></el-table-column>
      <el-table-column prop="address" width="200" label="地址"></el-table-column>
      <el-table-column prop="address" width="200" label="地址"></el-table-column>
      <el-table-column prop="address" width="200" label="地址"></el-table-column>
      <el-table-column prop="address" width="200" label="地址"></el-table-column>
      <el-table-column prop="address" width="200" label="地址"></el-table-column>
      <el-table-column prop="address" width="200" label="地址"></el-table-column>
    </el-table>
   
  </div>
</template>

<script>
export default {
  components: {},
  props:{
    // 封装表格的外层class,可不同表格设置不同class,防止单页面多表格js错乱
    stickyClassKey:{
        type:String,
        default:"tab2"
    },
    isSticky:{
        type:Boolean,
        default: false
    },
    // 设置表格相对于外层某个父元素进行吸顶
    stickyClass:{
        type:String,
        default:"tabBox"
    },
  },
  data() {
    return {
      // 测试数据
        tableData: [
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
            {date: '2016-05-02', name: '王小虎', address: '上海市普陀区金沙江路 1518 弄'},
        ],
        headerTimer:null,
        showShadow:false
    };
  },
  computed: {},
  watch: {},
  created() { },
  mounted() { 
    this.tabSticky()
  },
  methods: {
    // 表头吸顶
    tabSticky(){
      let stickyDom = document.querySelector('.isStickyTab') || null

      if(stickyDom && this.isSticky){
        this.$nextTick(() => {
          let stickyClass = this.stickyClass
          let stickyClassKey = this.stickyClassKey? `.${this.stickyClassKey}`:''
          
          let outDom = document.querySelector(`.${stickyClass}`)
          let contentBoxDom = document.querySelector(`${stickyClassKey} .stickyFixed .stickyFixedMainBox`)
          let domScoll = document.querySelector(`${stickyClassKey} .el-table__body-wrapper`)

          // outDom 实时滚动窗口大小变化
          window.onresize = () => {
            if(this.headerTimer){
              clearTimeout(this.headerTimer)
              this.headerTimer = null
            }
            this.headerTimer = setTimeout(() => {
              this.tabStickyFun()
            },100)
          }
          // outDom 实时滚动监听在(最外层浏览器页面下)
          outDom.addEventListener('scroll',this.tabStickyFun);

          // 表格横向滚动 监听
          domScoll.addEventListener('scroll',(e)=>{
            contentBoxDom.scrollLeft = e.target.scrollLeft
          });
          contentBoxDom.addEventListener('scroll',(e)=>{
            domScoll.scrollLeft = e.target.scrollLeft
          });

        })
      }
    },
    tabStickyFun(){
      let stickyClass = this.stickyClass
      let stickyClassKey = this.stickyClassKey? `.${this.stickyClassKey}`:''

      let stickyDom = document.querySelector(`.${stickyClass} .isStickyTab`) || null
      let outDom = document.querySelector(`.${stickyClass}`)
      let tabHeaderWrapperDom = document.querySelector(`${stickyClassKey} .isStickyTab .el-table__header-wrapper`)
      let tableDom = document.querySelector(`${stickyClassKey} .el-table`)
      let tabHeaderDom = document.querySelector(`${stickyClassKey} .el-table__header`)
      // 表格栏 fixed固定栏表头
      let tabHeaderDomLeft = document.querySelector(`${stickyClassKey} .isStickyTab .el-table__fixed`)
      let tabHeaderDomRight = document.querySelector(`${stickyClassKey} .isStickyTab .el-table__fixed-right`)
      let fixedLeftHeader = document.querySelector(`${stickyClassKey} .stickyFixed .fixedLeftHeader`)
      let fixedRightHeader = document.querySelector(`${stickyClassKey} .stickyFixed .fixedRightHeader`)
   
      let stickyFixedDom = document.querySelector(`${stickyClassKey} .stickyFixed`)
      let contentBoxDom = document.querySelector(`${stickyClassKey} .stickyFixed .stickyFixedMainBox`)
      let domScoll = document.querySelector(`${stickyClassKey} .el-table__body-wrapper`)
  
      // 给table el-table__header-wrapper 赋予高度 使table__header fixed的时候高度不会塌陷
      tabHeaderWrapperDom.style.height = tabHeaderDom.offsetHeight + 'px'
      let wrapperWidth = tabHeaderWrapperDom.offsetWidth
      stickyFixedDom.style.width = wrapperWidth + 'px'
      
      // 获取各个dom的位置参数
      let outDomOffsetTop = outDom.offsetTop
      let outDomScrollTop = outDom.scrollTop
      let tableDomHeight = tableDom.offsetHeight
      
      let domTop = this.getDom(stickyDom,outDom,0) || 0
      let stickyInOffset = (domTop - outDomOffsetTop) + tabHeaderDom.offsetHeight - tabHeaderDom.clientTop
      outDom.style.position = "relative"
      let tableOffsetAllHeight = (domTop - outDomOffsetTop - tabHeaderDom.clientTop) + tableDomHeight || 0
      
      if(outDomScrollTop >= stickyInOffset){
        let tabStickyFixedDom = tabHeaderWrapperDom.querySelector(".stickyFixed") || null
        if(!tabStickyFixedDom){
          contentBoxDom.appendChild(tabHeaderDom)
          tabHeaderWrapperDom.appendChild(stickyFixedDom)
        }

        this.showShadow = true
        if(outDomScrollTop >= tableOffsetAllHeight){
          stickyFixedDom.style.zIndex =  -10
        }else{
          // fixed 左边处理
          if(tabHeaderDomLeft && fixedLeftHeader.childNodes.length<1){
            let tabHeaderDomLeftWidth = document.querySelector(`${stickyClassKey} .isStickyTab .el-table__fixed`).offsetWidth
            fixedLeftHeader.style.width = tabHeaderDomLeftWidth + 'px'
            fixedLeftHeader.style.height = tabHeaderWrapperDom.offsetHeight + 'px'
            fixedLeftHeader.appendChild(tabHeaderDomLeft.querySelector(".el-table__fixed-header-wrapper"))
          }
          //fixed 右边边处理
          if(tabHeaderDomRight && fixedRightHeader.childNodes.length<1){
            let tabHeaderDomRightWidth = document.querySelector(`${stickyClassKey} .isStickyTab .el-table__fixed-right `).offsetWidth
            fixedRightHeader.style.width = tabHeaderDomRightWidth + 'px'
            fixedRightHeader.style.height = tabHeaderWrapperDom.offsetHeight + 'px'
            fixedRightHeader.appendChild(tabHeaderDomRight.querySelector(".el-table__fixed-header-wrapper"))
          }

          // 判断当前table横向是否有滚动条
          if(domScoll.scrollWidth > domScoll.clientWidth){
            fixedLeftHeader.style.display = 'block'
            fixedRightHeader.style.display = 'block'
          }else{
            if(tabHeaderDomRight){
              fixedLeftHeader.style.display = 'block'
            }else{
              fixedLeftHeader.style.display = 'none'
            }
            if(tabHeaderDomRight){
              fixedRightHeader.style.display = 'block'
            }else{
              fixedRightHeader.style.display = 'none'
            }
          }
          
          tabHeaderWrapperDom.style.position = "relative"
          stickyFixedDom.style.position =  'absolute'
          tabHeaderWrapperDom.style.overflow = "visible"
          let fixedScrollTop = outDomScrollTop - (domTop - outDomOffsetTop) 
          stickyFixedDom.style.top =  fixedScrollTop + 'px'

          stickyFixedDom.style.width =  tabHeaderWrapperDom.offsetWidth + 'px'
          stickyFixedDom.style.height =  tabHeaderWrapperDom.offsetHeight + 'px'
          stickyFixedDom.style.zIndex =  5
        }
      }else{
        stickyFixedDom.style.position = 'relative'
        stickyFixedDom.style.top = 'inherit'
        stickyFixedDom.style.zIndex =  1
        this.showShadow = false
      }
    },
    getDom(dom,outDom,top){
      let num = top
      num += dom.offsetTop
      let parent = dom.offsetParent
      if(parent && parent.isEqualNode(outDom.offsetParent)){
        return num
      }else{
        return this.getDom(parent,outDom,num)
      }
    },
  },//methods End
}
</script>
<style lang='less' scoped>
/*@import url(); 引入公共css类 */
.stickyFixed{
  position: absolute;
  z-index: -10;
  background-color: #f4f4f4;
  overflow: hidden;
  .stickyFixedContentBox{
    position: relative;
    width: 100%;
    height: 100%;
   
  }
  .stickyFixedMainBox{
    width: 100%;
    position: relative;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .fixedLeftHeader,
  .fixedRightHeader{
    position: absolute;
    z-index: 5;
    background-color: #f4f4f4;
    overflow: hidden;
    ::v-deep .is-hidden{
      // display: none !important;
      // opacity: 0;
    }
  }
  .fixedLeftHeader{
    left: 0;
    top: 0;
  }
  .leftShadow{
    box-shadow: 1px 0 10px rgba(0,0,0,.12);
  }
  .fixedRightHeader{
    right: 0;
    top: 0;
    ::v-deep .el-table__fixed-header-wrapper{
      right: 0;
      left: inherit !important;
    }
  }
  .rightShadow{
    box-shadow: -1px 0 10px rgba(0,0,0,.12);
  }

  ::v-deep .el-table__header{
    width: 100% !important;
    th{
      border: 1px solid #ebeef5;
      border-right: 0px;
      background-color: #f4f4f4;
      // background-color: transparent;
    }
    th:nth-last-child(2){
      border-right: 1px solid #EBEEF5;
    }
    
  }
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值