Maison  >  Article  >  php教程  >  Vue 固定头 固定列 点击表头可排序的表格组件

Vue 固定头 固定列 点击表头可排序的表格组件

高洛峰
高洛峰original
2016-12-05 11:16:511574parcourir

原理是将原table的指定行,指定列clone一份放在其上

实现代码如下:

<template> 
 <div> 
  <div id="divBox1" :style="{height:height}"> 
   <table id="tbTest1" cellpadding="0" cellspacing="0" style="text-align:center;background:rgba(244,249,255,0.4);"> 
    <tr> 
     <th v-for="item in thead" @click="sortBy(item)"> 
      {{item}}<img style="width:0.16rem;height:0.20rem;margin-left:4px;" :src="filterUrl" alt="" v-if="$index!=0" data-img="{{filterUrl}}"> 
     </th> 
    </tr> 
    <tr v-for="row in tableRows | orderBy sortBykey sortOrders[sortKey]"> 
     <td style="overflow:hidden;white-space:nowrap;" v-for="item in gridColumns" v-html="row[item] | numberFilter" :id="$parent.$index"> 
     </td> 
    </tr> 
   </table> 
  </div> 
 </div> 
</template> 
<script> 
 /*eslint-disable*/
 var ofixed_table_st = window.setTimeout; 
 var hasLeft = &#39;&#39;; 
 var hasHead = &#39;&#39;; 
 window.setTimeout = function(fRef, mDelay) { 
  if(typeof fRef == &#39;function&#39;) { 
   var argu = Array.prototype.slice.call(arguments, 2); 
   var f = (function() { 
    fRef.apply(null, argu); 
   }); 
   return ofixed_table_st(f, mDelay); 
  } 
  return ofixed_table_st(fRef, mDelay); 
 }; 
 function oFixedTable(id, obj, _cfg) { 
  this.id = id; 
  this.obj = obj; 
  this.box = this.obj.parentNode; 
  this.config = { 
   fixHead: _cfg.fixHead || true, 
   rows: _cfg.rows || 1, 
   cols: _cfg.cols || 0, 
   background: _cfg.background || &#39;#ffffff&#39;, 
   zindex: _cfg.zindex || 10 
  }; 
  window.setTimeout(this._fixTable, 100, this); 
 } 
 oFixedTable.prototype._fixTable = function(_) { 
  if(_.obj.rows.length <= 0) { 
   return false; 
  } 
  var hasLeft = _.buildLeft(); 
  var hasHead = _.buildHead(); 
  _.box.onscroll = function() { 
   if(_.divHead != null) { 
    _.divHead.scrollLeft = this.scrollLeft; 
   } 
   if(_.divLeft != null) { 
    _.divLeft.scrollTop = this.scrollTop; 
   } 
  }; 
  if(hasHead && hasLeft) { 
   _.buildTopLeft(); 
  } 
 }; 
 oFixedTable.prototype.buildHead = function() { 
  console.log(2222222222222222222) 
  var _ = this; 
  var strDivId = _.id + &#39;_div_head&#39;; 
  var strTbId = _.id + &#39;_tb_header&#39;; 
  var div = document.createElement(&#39;div&#39;); 
  div.id = strDivId; 
  div.style.cssText = &#39;position:absolute;overflow:hidden;z-index:&#39; + (_.config.zindex + 1) + &#39;;&#39;; 
  div.innerHTML = &#39;<table id="&#39; + strTbId + &#39;" cellpadding="0" cellspacing="0" style="background:&#39; + _.config.background + &#39;;"></table>&#39;; 
  _.box.insertBefore(div, _.obj); 
  _.divHead = div; 
  _.tbHead = document.getElementById(strTbId); 
  //判断是否出现纵向滚动条,若出现,高度减去滚动条宽度 16px 
  var sw = _.obj.offsetHeight > _.box.offsetHeight ? 0 : 0; 
  _.divHead.style.width = (_.box.offsetWidth - sw) + &#39;px&#39;; 
  _.tbHead.style.textAlign = _.obj.style.textAlign; 
  _.tbHead.style.width = _.obj.offsetWidth + &#39;px&#39;; 
  var hasHead = false; 
  if(_.config.fixHead && _.obj.tHead != null) { 
   var tHead = _.obj.tHead; 
   _.tbHead.appendChild(tHead.cloneNode(true)); 
   hasHead = true; 
  } else { 
   for(var i = 0; i < _.config.rows; i++) { 
    var row = _.obj.rows[i]; 
    if(row != null) { 
     _.tbHead.appendChild(row.cloneNode(true)); 
     hasHead = true; 
    } 
   } 
  } 
  return hasHead; 
 }; 
 oFixedTable.prototype.buildLeft = function() { 
  var _ = this; 
  if(_.config.cols <= 0) { 
   return false; 
  } 
  var strDivId = _.id + &#39;_div_left&#39;; 
  var strTbId = _.id + &#39;_tb_left&#39;; 
  var div = document.createElement(&#39;div&#39;); 
  div.id = strDivId; 
  div.style.cssText = &#39;position:absolute;overflow:hidden;z-index:&#39; + _.config.zindex + &#39;;box-shadow: #dddddd 2px 0px 2px;width: 2rem;&#39;; 
  div.innerHTML = &#39;<table id=&#39; + strTbId + &#39; cellpadding="0" cellspacing="0" style="background:&#39; + _.config.background + &#39;;width: 2rem;"></table>&#39;; 
  _.box.insertBefore(div, _.obj); 
  _.divLeft = div; 
  _.tbLeft = document.getElementById(strTbId); 
  _.tbLeft.style.textAlign = _.obj.style.textAlign; 
  //判断是否出现横向滚动条,若出现,高度减去滚动条高度 16px 
  var sw = _.obj.offsetWidth > _.box.offsetWidth ? 0 : 0; 
  _.divLeft.style.height = (_.box.offsetHeight - sw) + &#39;px&#39;; 
  var hasLeft = false; 
  for(var i = 0, rows = _.obj.rows.length; i < rows; i++) { 
   var row = _.tbLeft.insertRow(_.tbLeft.rows.length); 
   row.style.cssText = _.obj.rows[i].style.cssText; 
   for(var j = 0; j < _.config.cols; j++) { 
    var cell = _.obj.rows[i].cells[j]; 
    if(cell != null) { 
     row.appendChild(cell.cloneNode(true)); 
     cell.style.cssText = _.obj.rows[i].cells[j].style.cssText; 
     hasLeft = true; 
    } 
   } 
  } 
  return hasLeft; 
 }; 
 oFixedTable.prototype.buildTopLeft = function() { 
  var _ = this; 
  var strDivId = _.id + &#39;_div_top_left&#39;; 
  var strTbId = _.id + &#39;_tb_top_left&#39;; 
  var div = document.createElement(&#39;div&#39;); 
  div.id = strDivId; 
  div.style.cssText = &#39;position:absolute;overflow:hidden;z-index:&#39; + (_.config.zindex + 2) + &#39;;box-shadow: #dddddd 2px 0px 2px;width: 2rem;&#39;; 
  div.innerHTML = &#39;<table id="&#39; + strTbId + &#39;" cellpadding="0" cellspacing="0" style="background:&#39; + _.config.background + &#39;;"></table>&#39;; 
  _.box.insertBefore(div, _.obj); 
  var tbTopLeft = document.getElementById(strTbId); 
  tbTopLeft.style.textAlign = _.obj.style.textAlign; 
  for(var i = 0; i < _.config.rows; i++) { 
   var row = tbTopLeft.insertRow(tbTopLeft.rows.length); 
   row.style.cssText = _.obj.rows[i].style.cssText; 
   for(var j = 0; j < _.config.cols; j++) { 
    var cell = _.obj.rows[i].cells[j]; 
    if(cell != null) { 
     row.appendChild(cell.cloneNode(true)); 
     cell.style.cssText = _.obj.rows[i].cells[j].style.cssText; 
     hasLeft = true; 
    } 
   } 
  } 
 }; 
 export default{ 
  // 接收父组件传过来的参数 
  props: [&#39;tableRows&#39;, &#39;gridColumns&#39;, &#39;thead&#39;, &#39;store&#39;, &#39;height&#39;, &#39;singleData&#39;], 
  // 监控 
  watch: { 
   &#39;tableRows&#39;: function (val) { 
    var self = this
    // 明星店铺页面时动态调整店铺名所在列的宽度s 
    if (self.store) { 
     document.querySelectorAll(&#39;table td:nth-child(3)&#39;)[0].style.width = 3 + &#39;rem&#39;
     document.querySelectorAll(&#39;table th:nth-child(3)&#39;)[0].style.width = 3 + &#39;rem&#39;
    } 
    var length = self.gridColumns.length 
    document.getElementById(&#39;tbTest1&#39;).style.width = 2 * length + &#39;rem&#39;
    setTimeout(function () { 
     if (self.singleData) { 
      document.getElementById(&#39;ofix1_tb_left&#39;).classList.add(&#39;ofix1_tb_left&#39;) 
     } 
     document.querySelectorAll(&#39;#ofix1_tb_left td&#39;)[0].style.width = 2 + &#39;rem&#39;
     var tbObj = document.getElementById(&#39;ofix1_tb_header&#39;) 
     tbObj.addEventListener(&#39;click&#39;,function (event) { 
      if(event.target.tagName === &#39;TH&#39;){ 
       self.sortBy(event.target.innerText, event) 
      } 
     }) 
    }, 101) 
   } 
  }, 
  data: function() { 
   var sortOrders = {} 
   this.gridColumns.forEach(function (key) { 
    sortOrders[key] = 1 
   }) 
   return { 
    sortKey: &#39;&#39;, 
    filterUrl: &#39;./static/img/indus/filter1.png&#39;, 
    sortOrders: sortOrders 
   } 
  }, 
  methods: { 
   sortBykey: function (a, b) { 
    return parseFloat(a[this.sortKey]) - parseFloat(b[this.sortKey]) 
    console.log(&#39;11111111111&#39;) 
   }, 
   sortBy: function (key, event) { 
    // 每一次排序之前所有的图片重置 
    var imgDom = document.querySelectorAll(&#39;#ofix1_tb_header th img&#39;) 
    for (var x = 0; x < imgDom.length; x++) { 
     imgDom[x].setAttribute(&#39;src&#39;, &#39;./static/img/indus/filter1.png&#39;) 
    } 
    // 排序 
    var activeTheadIndex = 0 
    for (var i = 0; i < this.thead.length; i++) { 
     if (this.thead[i] === key) { 
      activeTheadIndex = i 
     } 
    } 
    this.sortKey = this.gridColumns[activeTheadIndex] 
    this.sortOrders[this.gridColumns[activeTheadIndex]] = this.sortOrders[this.gridColumns[activeTheadIndex]] * -1 
    // 排序时同步改变标识图片 
    if (this.sortOrders[this.gridColumns[activeTheadIndex]] > 0) { 
     event.target.getElementsByTagName(&#39;img&#39;)[0].setAttribute(&#39;src&#39;, &#39;./static/img/indus/filter2.png&#39;) 
    } else { 
     event.target.getElementsByTagName(&#39;img&#39;)[0].setAttribute(&#39;src&#39;, &#39;./static/img/indus/filter3.png&#39;) 
    } 
    // 排序时同步改变左边第一列的内容 
    setTimeout(function(){ 
     var tdDom = document.querySelectorAll(&#39;#tbTest1 tr td:nth-child(1)&#39;) 
     var tdDomLeft = document.querySelectorAll(&#39;#ofix1_tb_left td&#39;) 
     for (var y = 0; y < tdDom.length; y++) { 
      tdDomLeft[y].innerHTML = tdDom[y].innerHTML 
     } 
    },0) 
   } 
  }, 
  filters: { 
   numberFilter: function (value) { 
    if (value == 0) { 
     return &#39;0&#39;
    } else if (!value) { 
     return &#39;/&#39;
    } else { 
     return value 
    } 
   } 
  }, 
  components: { 
  }, 
  ready: function() { 
   var ofix1 = new oFixedTable(&#39;ofix1&#39;, document.getElementById(&#39;tbTest1&#39;), { 
    rows: 1, 
    cols: 1 
   }) 
  }, 
  created () { 
  } 
 } 
</script> 
<style scoped>
 #divBox1{ 
  overflow:auto; 
  width:100%; 
  font-size: 0.28rem; 
 }
 #ofix1_div_left{ 
  box-shadow: #dddddd 2px 0px 2px; 
  width: 2rem; 
 } 
 table { 
  table-layout : fixed; 
 } 
 table td, 
 table th { 
  width: 2rem; 
  line-height: 1rem; 
  height: 1rem; 
  padding: 0; 
  color: #999999; 
  overflow: hidden; 
  white-space: nowrap; 
  /*vertical-align: middle;*/
 } 
 table th{ 
  background: rgba(188,219,255,0.4); 
  color: #999; 
  font-size: .28rem; 
  font-weight: normal; 
 } 
 table th:nth-child(1){ 
  box-shadow: #dddddd 2px 0px 0px; 
 } 
 .ofix1_tb_left tr td:nth-child(1){ 
  /*display: inline-block;*/
  text-align: left; 
 }
 #ofix1_div_top_left{ 
  box-shadow: #dddddd 2px 0px 2px; 
 }
 #tbTest1 tr td:nth-child(1){ 
  box-shadow: #dddddd 2px 0px 0px; 
 }
 #tbheader td { 
  background: #fff; 
 } 
</style>

父组件调用实例:

<template> 
   <table-locked :table-rows="tableData" :grid-columns="gridColumns" :thead="thead" :height="height"> 
   </table-locked> 
</template> 
import TableLocked from &#39;../../common/TableLocked.vue&#39;
export default{ 
  components: {TableLocked}, 
  data () { 
    data.gridColumns = [&#39;brand&#39;, &#39;product_count&#39;, &#39;averagePrice&#39;, &#39;sales&#39;, &#39;huang_sale_per&#39;, &#39;sale_per&#39;, &#39;sales_amount&#39;, &#39;huang_sale_amount_per&#39;, &#39;sales_amount_per&#39;, &#39;score_num&#39;, &#39;scort_good_per&#39;] 
   data.thead = [&#39;品类&#39;, &#39;产品种类&#39;, &#39;均价&#39;, &#39;销量&#39;, &#39;销量环比&#39;, &#39;销量占比&#39;, &#39;销额(万元)&#39;, &#39;销额环比&#39;, &#39;销额占比&#39;, &#39;评论总数&#39;, &#39;好评率&#39;] 
  } 
}


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn