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 相关文章推荐
js 替换功能函数,用正则表达式解决,js的全部替换
Dec 08 Javascript
.net,js捕捉文本框回车键事件的小例子(兼容多浏览器)
Mar 11 Javascript
如何获取网站icon有哪些可行的方法
Jun 05 Javascript
Jquery中Event对象属性小结
Feb 27 Javascript
js实现iGoogleDivDrag模块拖动层拖动特效的方法
Mar 04 Javascript
基于HTML5上使用iScroll实现下拉刷新,上拉加载更多
May 21 Javascript
解决bootstrap导航栏navbar在IE8上存在缺陷的方法
Jul 01 Javascript
js实现数字递增特效【仿支付宝我的财富】
May 05 Javascript
Vue组件通信之Bus的具体使用
Dec 28 Javascript
Node实战之不同环境下配置文件使用教程
Jan 02 Javascript
基于vue-cli 打包时抽离项目相关配置文件详解
Mar 07 Javascript
js canvas实现橡皮擦效果
Dec 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
150kHz到30Mhz完全冲浪手册
2020/03/20 无线电
redis 队列操作的例子(php)
2012/04/12 PHP
Linux(CentOS)下PHP扩展PDO编译安装的方法
2016/04/07 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
2017/07/20 PHP
在thinkphp5.0路径中实现去除index.php的方式
2019/10/16 PHP
javascript 快速排序函数代码
2012/05/30 Javascript
来自国外的30个基于jquery的Web下拉菜单
2012/06/22 Javascript
使用JavaScript的AngularJS库编写hello world的方法
2015/06/23 Javascript
Bootstrap学习系列之使用 Bootstrap Typeahead 组件实现百度下拉效果
2016/07/07 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
2016/09/04 Javascript
JS获取鼠标相对位置的方法
2016/09/20 Javascript
详解Js模板引擎(TrimPath)
2016/11/22 Javascript
JS求Number类型数组中最大元素方法
2018/04/08 Javascript
vue组件开发之用户无限添加自定义填写表单的方法
2018/08/28 Javascript
Bootbox将后台JSON数据填充Form表单的实例代码
2018/09/10 Javascript
node使用mysql获取数据库数据中文乱码问题的解决
2019/12/02 Javascript
vue+element UI实现树形表格
2020/12/29 Vue.js
[41:56]Spirit vs Liquid Supermajor小组赛A组 BO3 第一场 6.2
2018/06/03 DOTA
Python求两个list的差集、交集与并集的方法
2014/11/01 Python
Python json模块使用实例
2015/04/11 Python
python实现数值积分的Simpson方法实例分析
2015/06/05 Python
详谈python在windows中的文件路径问题
2018/04/28 Python
Django框架实现逆向解析url的方法
2018/07/04 Python
Python字符串的全排列算法实例详解
2019/01/07 Python
如何使用Python抓取网页tag操作
2020/02/14 Python
Django media static外部访问Django中的图片设置教程
2020/04/07 Python
Python基于Twilio及腾讯云实现国际国内短信接口
2020/06/18 Python
HTML5单页面手势滑屏切换原理分析
2017/07/10 HTML / CSS
西班牙第一的网上药房:PromoFarma.com
2017/04/17 全球购物
捷克汽车配件和工具销售网站:TorriaCars
2018/02/26 全球购物
Lacoste澳大利亚官网:服装、鞋类及配饰
2018/11/14 全球购物
JoJo Maman Bébé爱尔兰官网:英国最受欢迎的精品母婴品牌
2020/12/20 全球购物
职业培训师职业生涯规划
2014/02/18 职场文书
创卫工作总结2015
2015/04/22 职场文书
幼儿园六一主持词开场白
2015/05/28 职场文书
用Python编写简单的gRPC服务的详细过程
2021/07/04 Python