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 相关文章推荐
JavaScript基本概念初级讲解论坛贴的学习记录
Feb 22 Javascript
电子商务网站上的常用的js放大镜效果
Dec 08 Javascript
在jQuery ajax中按钮button和submit的区别分析
Oct 07 Javascript
JavaScript自定义方法实现trim()、Ltrim()、Rtrim()的功能
Nov 03 Javascript
JS获取计算机mac地址以及IP的实现方法
Jan 08 Javascript
js 获取页面高度和宽度兼容 ie firefox chrome等
May 14 Javascript
Javascript核心读书有感之语句
Feb 11 Javascript
HTML5 Shiv完美解决IE(IE6/IE7/IE8)不兼容HTML5标签的方法
Nov 25 Javascript
angularjs ui-router中路由的二级嵌套
Mar 10 Javascript
微信小程序之前台循环数据绑定
Aug 18 Javascript
vue2.0实现音乐/视频播放进度条组件
Jun 06 Javascript
JavaScript对象拷贝与Object.assign用法实例分析
Jun 20 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代码包装修正版
2008/03/15 PHP
神盾加密解密教程(一)PHP变量可用字符
2014/05/28 PHP
完善CodeIgniter在IDE中代码提示功能的方法
2014/07/19 PHP
PHP经典面试题之设计模式(经常遇到)
2015/10/15 PHP
php-fpm中max_children的配置
2019/03/15 PHP
Nigma vs Liquid BO3 第一场2.14
2021/03/10 DOTA
Javascript insertAfter() 实现函数代码
2011/10/12 Javascript
XMLHttpRequest处理xml格式的返回数据(示例代码)
2013/11/21 Javascript
javascript框架设计读书笔记之字符串的扩展和修复
2014/12/02 Javascript
JavaScript过滤字符串中的中文与空格方法汇总
2016/03/07 Javascript
JavaScript中的原型继承基础学习教程
2016/05/06 Javascript
详解JS对象封装的常用方式
2016/12/30 Javascript
jQuery返回定位插件详解
2017/05/15 jQuery
Node.js 8 中的重要新特性
2017/06/28 Javascript
分析JS中this引发的bug
2017/12/12 Javascript
详解CommonJS和ES6模块循环加载处理的区别
2018/12/26 Javascript
用Fundebug插件记录网络请求异常的方法
2019/02/21 Javascript
vue 表单输入框不支持focus及blur事件的解决方案
2020/11/17 Vue.js
[33:42]LGD vs OG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
[02:53]2018年度DOTA2最佳战队-完美盛典
2018/12/17 DOTA
利用QT写一个极简单的图形化Python闹钟程序
2015/04/07 Python
Python中遍历字典过程中更改元素导致异常的解决方法
2016/05/12 Python
python实现拼接图片
2020/03/23 Python
Python基于smtplib模块发送邮件代码实例
2020/05/29 Python
纯css3制作的火影忍者写轮眼开眼至轮回眼及进化过程实例
2014/11/11 HTML / CSS
2014年元旦促销活动方案
2014/02/22 职场文书
文案策划求职信
2014/03/18 职场文书
2014年师德承诺书
2014/05/23 职场文书
2014教师专业技术工作总结
2014/12/03 职场文书
2014年学校后勤工作总结
2014/12/06 职场文书
学雷锋日活动总结
2015/02/06 职场文书
2015年乡镇卫生院工作总结
2015/04/22 职场文书
网吧员工管理制度
2015/08/05 职场文书
停车场管理制度范本
2015/08/05 职场文书
聘任书格式及范文
2015/09/21 职场文书
2016年小学中秋节活动总结
2016/04/05 职场文书