模擬滾動(dòng)條與表格性能優(yōu)化

模擬滾動(dòng)條是在禁用瀏覽器自帶滾動(dòng)條后使用html和js代碼自定義實(shí)現(xiàn)滾動(dòng)條效果

首先需要設(shè)置原有出現(xiàn)滾動(dòng)條的元素 overfolw:hidden

需要用到的事件有鼠標(biāo)滾輪事件,mousemove,mouseup,mouseleave,mousedown(其中mousedown事件是放置在滾動(dòng)條或者滾動(dòng)滑塊上的)

基于上一篇關(guān)于隊(duì)列的文章,我們添加了這些事件

以下代碼基于element-ui的表格控件table實(shí)現(xiàn)

<div class="el-table__body-scrollbar" ref="scrollBar" :style="[bodyHeight]">
        <div class="scroll_block" @mousedown="mouseDown"></div>
</div>


mouseEvent.addEvent(this,this.mouseMove,"mousemove");
mouseEvent.addEvent(this,this.mouseUp,"mouseup");   
mouseEvent.addEvent(this,this.mouseLeave,"mouseleave");
mouseEvent.addEvent(this,this.mouseWeel);

html部分就不做全部展示了,將以上代碼中的html部分放到合適的地方或者自己寫

/**
 *this.barHeight滾動(dòng)條中滾動(dòng)塊的高度
 *this.scrollHeight滾動(dòng)條本身的高度
 *this.tableHeight表格內(nèi)部整體高度所有表格的高度和
 *以下所有阻止冒泡事件可以封裝
*/

//滾動(dòng)條中滾動(dòng)塊在鼠標(biāo)按下時(shí)
mouseDown(e){
  this.isDrag=true;//標(biāo)識(shí)參數(shù) 表示通過可以拖動(dòng)了
  this.pageY=e.pageY;//記錄初始的縱向位置
  //以下阻止冒泡部分可以封裝公用
  if(e.stopPropagation) e.stopPropagation();
  e.cancelBubble=true;
  e.returnValue=false;
  return false;
}

mouseMove(event){
  if(this.isDrag){
    var tar=this.$refs.scrollBar.children.item(0);//沒有直接使用ref,取的是滾動(dòng)塊
    var mv=event.pageY-this.pageY;//移動(dòng)量
    var top=tar.style.top;//當(dāng)前滾動(dòng)塊的top 位置
    if(top){//如果存在
      top=parseFloat(top.replace("px",""));//得出具體數(shù)值
      if((mv+this.barHeight+top)>this.scrollHeight){//如果移動(dòng)量加塊本身的高度加原有的top位置大于了滾動(dòng)條的高度
        mv=this.scrollHeight-this.barHeight;//移動(dòng)量保持在最底部
      }else if((mv+top)<0){//如果是向上滑動(dòng)并且超出了頂部  保留在頂部
        mv=0;
      }else{//正常情況   相加就行
        mv=top+mv;
      }
    }else{
      if((mv+this.barHeight)>this.scrollHeight){//同上一種情況,去掉top的影響,去掉相加的情況
            mv=this.scrollHeight-this.barHeight;
      }else if(mv<0){mv=0;}
    }
    this.adjust(mv);//具體執(zhí)行函數(shù),執(zhí)行滾動(dòng)條位置變換操作
    this.pageY=event.pageY;//保存當(dāng)前位置
    if(!this.simulate){//不可分頁  在不可分頁的情況 可能實(shí)際數(shù)據(jù)與顯示數(shù)據(jù)不一致 這里是將滾動(dòng)事件分發(fā)到了父組件
      this.$emit('bar-scroll',event,mv,this.barHeight);
    }
    if(event.stopPropagation) event.stopPropagation();
    if(event.preventDefault) event.preventDefault();
    event.cancelBubble=true;
    event.returnValue=false;
    return false;
  }
}

//這里習(xí)慣性的使用了原生js
adjust(mv){
  if(typeof mv=='number'){
    var tar=this.$refs.scrollBar.children.item(0);
    var table=this.bodyWrapper.querySelector(".el-table__body");
    tar.style.top=mv+"px";
    //到了這里mv代表的就是新的top屬性  這是常規(guī)算法
    //使用marginTop調(diào)整塊的位置
    table.style.marginTop=-(mv*(this.tableHeight-this.scrollHeight))/(this.scrollHeight-this.barHeight)+"px";
  }
}

//當(dāng)鼠標(biāo)結(jié)束按下的狀態(tài)后
mouseUp(e){
   if(this.isDrag){
    this.isDrag = false;//標(biāo)識(shí)設(shè)置為否
    if (e.stopPropagation) e.stopPropagation();
    e.cancelBubble = true;
    e.returnValue = false;
    return false;  
   }
}
//離開作用范圍后
mouseLeave(event){
  this.isDrag=false;
},

//鼠標(biāo)滾輪滾動(dòng)時(shí)的操作
mouseWeel(event){
  //先判斷作用域范圍是否是當(dāng)前組件
  event = event || window.event;
  var tar=this.bodyWrapper;
  var target=event.target;
  if(tar.contains(target)){
    var scrollBar=this.$refs.scrollBar;
    var bar=scrollBar.children.item(0);
    var resize=this.simulate?1:(100/this.total);
    var top=bar.style.top,step=(100*this.scrollHeight*resize)/this.tableHeight;
    if(scrollBar.style.display!="none"){
      top=parseFloat(top.replace("px",""));
      if (event.wheelDelta) {  //判斷瀏覽器IE,谷歌滑輪事件    
        //當(dāng)滑輪向上滾動(dòng)時(shí)
        if (event.wheelDelta > 0) {
          if((top-step)<=0){
            this.adjust(0);
          }else{
            this.adjust(top-step);
          }
          if(top>0){
            if(event.stopPropagation) event.stopPropagation();
            if(event.preventDefault) event.preventDefault();
            event.cancelBubble=true;
            event.returnValue=false;
            return false;
          }
        }
        //當(dāng)滑輪向下滾動(dòng)時(shí)  
        if (event.wheelDelta < 0) {
          if((top+step+this.barHeight)>=this.scrollHeight){
            this.adjust(this.scrollHeight-this.barHeight);
          }else{
            this.adjust(top+step);
          }
          if((top+this.barHeight)<(this.scrollHeight-0.01)){
            if(event.stopPropagation) event.stopPropagation();
              if(event.preventDefault) event.preventDefault();
              event.cancelBubble=true;
              event.returnValue=false;
              return false;
          }
        }
      } else if (event.detail) {  //Firefox滑輪事件  
        if (event.detail< 0) {
          if((top-step)<=0){
            this.adjust(0);
          }else{
            this.adjust(top-step);
          }
          if(top>0){
            if(event.stopPropagation) event.stopPropagation();
            if(event.preventDefault) event.preventDefault();
            event.cancelBubble=true;
            event.returnValue=false;
            return false;
          }
        }
        if (event.detail> 0) {
          if((top+step+this.barHeight)>=this.scrollHeight){
            this.adjust(this.scrollHeight-this.barHeight);
          }else{
            this.adjust(top+step);
          }
          if((top+this.barHeight)<this.scrollHeight){
            if(event.stopPropagation) event.stopPropagation();
            if(event.preventDefault) event.preventDefault();
            event.cancelBubble=true;
            event.returnValue=false;
            return false;
          }
         }
       }
     }
   }
  }
}

//執(zhí)行位置更新操作  并初始化相關(guān)參數(shù)
//判斷是否需要顯示滾動(dòng)條
//代碼可能不那么vue 不過不重要
scrollBarSet(){
  var scrollBar=this.$refs.scrollBar;
  if(scrollBar){
    var body=this.bodyWrapper,table=body.querySelector(".el-table__body");
    var bar=scrollBar.children.item(0);
    var extraHgt=table.offsetWidth>body.offsetWidth?10:0;//設(shè)置額外高度。主要是底部滾動(dòng)條高度這里設(shè)置為10
    if(body.offsetHeight>=(table.offsetHeight+extraHgt)){
      scrollBar.style.display="none";
      bar.style.top="";
      bar.style.height="";
      this.adjust(0);
    }else{
      scrollBar.style.display="block";
      var height=(body.offsetHeight*scrollBar.offsetHeight)/(table.offsetHeight+extraHgt);
      if(height<20){//當(dāng)數(shù)據(jù)量過大的時(shí)候保持滾動(dòng)塊最少20px
        height=20;
      }
      bar.style.height=height+"px";
      this.scrollHeight=scrollBar.offsetHeight;
      this.tableHeight=table.offsetHeight+extraHgt;
      this.barHeight=height;
      var top=bar.style.top;
      if(top){
        top=parseFloat(top.replace("px",""));
        if((top+height)>this.scrollHeight){
          top=this.scrollHeight-height;
        }
      }else{top=0;}
        this.adjust(top);
      }
  }
},

以上代碼可以實(shí)現(xiàn)正常情況下的模擬滾動(dòng)條功能
如果需要實(shí)現(xiàn)在數(shù)據(jù)量特別大的時(shí)候只加載顯示部分?jǐn)?shù)據(jù)
并且根據(jù)相關(guān)事件在滾動(dòng)過程中變換數(shù)據(jù)實(shí)現(xiàn)從顯示上加載了全部數(shù)據(jù)的形式
就需要在實(shí)際的控件中手動(dòng)去切換數(shù)據(jù)并配合預(yù)留的bar-scroll分發(fā)實(shí)現(xiàn)了

這部分就不貼代碼了,完成了這個(gè)步驟表格就不會(huì)應(yīng)為數(shù)據(jù)量而造成嚴(yán)重性能問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容