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


Posted in Javascript onNovember 25, 2016

原理是将原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 = ''; 
 var hasHead = ''; 
 window.setTimeout = function(fRef, mDelay) { 
  if(typeof fRef == 'function') { 
   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 || '#ffffff', 
   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 + '_div_head'; 
  var strTbId = _.id + '_tb_header'; 
  var div = document.createElement('div'); 
  div.id = strDivId; 
  div.style.cssText = 'position:absolute;overflow:hidden;z-index:' + (_.config.zindex + 1) + ';'; 
  div.innerHTML = '<table id="' + strTbId + '" cellpadding="0" cellspacing="0" style="background:' + _.config.background + ';"></table>'; 
  _.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) + 'px'; 
  _.tbHead.style.textAlign = _.obj.style.textAlign; 
  _.tbHead.style.width = _.obj.offsetWidth + 'px'; 
  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 + '_div_left'; 
  var strTbId = _.id + '_tb_left'; 
  var div = document.createElement('div'); 
  div.id = strDivId; 
  div.style.cssText = 'position:absolute;overflow:hidden;z-index:' + _.config.zindex + ';box-shadow: #dddddd 2px 0px 2px;width: 2rem;'; 
  div.innerHTML = '<table id=' + strTbId + ' cellpadding="0" cellspacing="0" style="background:' + _.config.background + ';width: 2rem;"></table>'; 
  _.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) + 'px'; 
  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 + '_div_top_left'; 
  var strTbId = _.id + '_tb_top_left'; 
  var div = document.createElement('div'); 
  div.id = strDivId; 
  div.style.cssText = 'position:absolute;overflow:hidden;z-index:' + (_.config.zindex + 2) + ';box-shadow: #dddddd 2px 0px 2px;width: 2rem;'; 
  div.innerHTML = '<table id="' + strTbId + '" cellpadding="0" cellspacing="0" style="background:' + _.config.background + ';"></table>'; 
  _.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: ['tableRows', 'gridColumns', 'thead', 'store', 'height', 'singleData'], 
  // 监控 
  watch: { 
   'tableRows': function (val) { 
    var self = this 
    // 明星店铺页面时动态调整店铺名所在列的宽度s 
    if (self.store) { 
     document.querySelectorAll('table td:nth-child(3)')[0].style.width = 3 + 'rem' 
     document.querySelectorAll('table th:nth-child(3)')[0].style.width = 3 + 'rem' 
    } 
    var length = self.gridColumns.length 
    document.getElementById('tbTest1').style.width = 2 * length + 'rem' 
    setTimeout(function () { 
     if (self.singleData) { 
      document.getElementById('ofix1_tb_left').classList.add('ofix1_tb_left') 
     } 
     document.querySelectorAll('#ofix1_tb_left td')[0].style.width = 2 + 'rem' 
     var tbObj = document.getElementById('ofix1_tb_header') 
     tbObj.addEventListener('click',function (event) { 
      if(event.target.tagName === 'TH'){ 
       self.sortBy(event.target.innerText, event) 
      } 
     }) 
    }, 101) 
   } 
  }, 
  data: function() { 
   var sortOrders = {} 
   this.gridColumns.forEach(function (key) { 
    sortOrders[key] = 1 
   }) 
   return { 
    sortKey: '', 
    filterUrl: './static/img/indus/filter1.png', 
    sortOrders: sortOrders 
   } 
  }, 
  methods: { 
   sortBykey: function (a, b) { 
    return parseFloat(a[this.sortKey]) - parseFloat(b[this.sortKey]) 
    console.log('11111111111') 
   }, 
   sortBy: function (key, event) { 
    // 每一次排序之前所有的图片重置 
    var imgDom = document.querySelectorAll('#ofix1_tb_header th img') 
    for (var x = 0; x < imgDom.length; x++) { 
     imgDom[x].setAttribute('src', './static/img/indus/filter1.png') 
    } 
    // 排序 
    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('img')[0].setAttribute('src', './static/img/indus/filter2.png') 
    } else { 
     event.target.getElementsByTagName('img')[0].setAttribute('src', './static/img/indus/filter3.png') 
    } 
    // 排序时同步改变左边第一列的内容 
    setTimeout(function(){ 
     var tdDom = document.querySelectorAll('#tbTest1 tr td:nth-child(1)') 
     var tdDomLeft = document.querySelectorAll('#ofix1_tb_left td') 
     for (var y = 0; y < tdDom.length; y++) { 
      tdDomLeft[y].innerHTML = tdDom[y].innerHTML 
     } 
    },0) 
   } 
  }, 
  filters: { 
   numberFilter: function (value) { 
    if (value == 0) { 
     return '0' 
    } else if (!value) { 
     return '/' 
    } else { 
     return value 
    } 
   } 
  }, 
  components: { 
  }, 
  ready: function() { 
   var ofix1 = new oFixedTable('ofix1', document.getElementById('tbTest1'), { 
    rows: 1, 
    cols: 1 
   }) 
  }, 
  created () { 
  } 
 } 
</script> 
<style lang="scss" 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 '../../common/TableLocked.vue' 
export default{ 
  components: {TableLocked}, 
  data () { 
    data.gridColumns = ['brand', 'product_count', 'averagePrice', 'sales', 'huang_sale_per', 'sale_per', 'sales_amount', 'huang_sale_amount_per', 'sales_amount_per', 'score_num', 'scort_good_per'] 
   data.thead = ['品类', '产品种类', '均价', '销量', '销量环比', '销量占比', '销额(万元)', '销额环比', '销额占比', '评论总数', '好评率'] 
  } 
}

以上所述是小编给大家介绍的Vue 固定头 固定列 点击表头可排序的表格组件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
php上传图片并给图片打上透明水印的代码
Jun 07 Javascript
JS文本框默认值处理详解
Jul 10 Javascript
jQuery列表拖动排列具体实现
Nov 04 Javascript
jQuery实现新消息闪烁标题提示的方法
Mar 11 Javascript
原生 JS Ajax,GET和POST 请求实例代码
Jun 08 Javascript
详解js中的apply与call的用法
Jul 30 Javascript
javascript轮播图算法
Oct 21 Javascript
JavaScript实现简单的四则运算计算器完整实例
Apr 28 Javascript
node.js+express+mySQL+ejs+bootstrop实现网站登录注册功能
Jan 12 Javascript
学习React中ref的两个demo示例
Aug 14 Javascript
对vue下点击事件传参和不传参的区别详解
Sep 15 Javascript
Three.js实现3D机房效果
Dec 30 Javascript
AngularJs验证重复密码的方法(两种)
Nov 25 #Javascript
jQuery实现发送验证码并60秒倒计时功能
Nov 25 #Javascript
js document.getElementsByClassName的使用介绍与自定义函数
Nov 25 #Javascript
微信JS-SDK自定义分享功能实例详解【分享给朋友/分享到朋友圈】
Nov 25 #Javascript
JS实现的图片预览插件与用法示例【不上传图片】
Nov 25 #Javascript
微信小程序开发之实现选项卡(窗口顶部TabBar)页面切换
Nov 25 #Javascript
Javascript基于jQuery UI实现选中区域拖拽效果
Nov 25 #Javascript
You might like
解析在PHP中使用mysqli扩展库对mysql的操作
2013/07/03 PHP
PHP 7.0.2 正式版发布
2016/01/08 PHP
PHP7匿名类用法分析
2016/09/26 PHP
PHP基于DOM创建xml文档的方法示例
2017/02/08 PHP
PHP使Laravel为JSON REST API返回自定义错误的问题
2018/10/16 PHP
javascript 进阶篇2 CSS XML学习
2012/03/14 Javascript
js解决select下拉选不中问题
2014/10/14 Javascript
JavaScript学习心得之概述
2015/01/20 Javascript
javascript实现选中复选框后相关输入框变灰不可用的方法
2015/08/11 Javascript
React Native实现简单的登录功能(推荐)
2016/09/19 Javascript
Angular.js中$apply()和$digest()的深入理解
2016/10/13 Javascript
js数字计算 误差问题的快速解决方法
2017/02/28 Javascript
详解React开发必不可少的eslint配置
2018/02/05 Javascript
ES6 新增的创建数组的方法(小结)
2019/08/01 Javascript
Layer+Echarts构建弹出层折线图的方法
2019/09/25 Javascript
[05:49]2014DOTA2TI4正赛第二日综述 昔日冠军纷纷落马 VG LGD占尽先机
2014/07/20 DOTA
[47:18]完美世界DOTA2联赛循环赛 IO vs FTD BO2第一场 11.05
2020/11/06 DOTA
python错误:AttributeError: 'module' object has no attribute 'setdefaultencoding'问题的解决方法
2014/08/22 Python
Django原生sql也能使用Paginator分页的示例代码
2017/11/15 Python
Python3.5文件修改操作实例分析
2019/05/01 Python
python处理大日志文件
2019/07/23 Python
简单了解python 生成器 列表推导式 生成器表达式
2019/08/22 Python
Python利用多线程同步锁实现多窗口订票系统(推荐)
2019/12/22 Python
基于Python的图像阈值化分割(迭代法)
2020/11/20 Python
html5 worker 实例(二) 图片变换效果
2013/06/24 HTML / CSS
sort命令的作用和用法
2012/11/04 面试题
纪律教育月活动总结
2014/08/26 职场文书
解放思想大讨论活动心得体会
2014/09/11 职场文书
党员检讨书
2014/10/13 职场文书
2015大学生党员自我评价范文
2015/03/03 职场文书
基层医务人员三严三实心得体会
2016/01/05 职场文书
2019感恩宣传标语!
2019/07/05 职场文书
导游词之永泰公主墓
2019/12/04 职场文书
详解nginx进程锁的实现
2021/06/14 Servers
Python道路车道线检测的实现
2021/06/27 Python
php实例化对象的实例方法
2021/11/17 PHP