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 相关文章推荐
node.js 一个简单的页面输出实现代码
Mar 07 Javascript
JS幻灯片可循环播放可平滑旋转带滚动导航(自写)
Aug 05 Javascript
5分钟理解JavaScript中this用法分享
Nov 09 Javascript
jQuery的选择器中的通配符[id^='code']或[name^='code']及jquery选择器总结
Dec 24 Javascript
基于JS代码实现图片在页面中旋转效果
Jun 16 Javascript
AngularJS基础 ng-src 指令简单示例
Aug 03 Javascript
详解jquery validate实现表单验证 (正则表达式)
Jan 18 Javascript
原生JS实现前端本地文件上传
Sep 08 Javascript
微信小程序--获取用户地理位置名称(无须用户授权)的方法
Apr 29 Javascript
微信小程序封装的HTTP请求示例【附升级版】
May 11 Javascript
详解小程序用户登录状态检查与更新实例
May 15 Javascript
使用Bootstrap做一个朝代历史表
Dec 10 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 Notice: Undefined index 错误提示解决方法
2010/08/29 PHP
zend api扩展的php对象的autoload工具
2011/04/18 PHP
php实现信用卡校验位算法THE LUHN MOD-10示例
2014/05/07 PHP
PHP PDO和消息队列的个人理解与应用实例分析
2019/11/25 PHP
用javascript实现的激活输入框后隐藏初始内容
2007/06/29 Javascript
jQuery 操作下拉列表框实现代码
2010/02/22 Javascript
JavaScript中将一个值转换为字符串的方法分析[译]
2012/09/21 Javascript
js正则表达式的使用详解
2013/07/09 Javascript
jquery限定文本框只能输入数字即整数和小数
2013/11/29 Javascript
jquery选择器大全 全面详解jquery选择器
2014/03/06 Javascript
常用的jquery模板插件——jQuery Boilerplate介绍
2014/09/23 Javascript
JS实现页面超时后自动跳转到登陆页面
2015/01/19 Javascript
深入理解JavaScript中的箭头函数
2015/07/28 Javascript
vue2.0构建单页应用最佳实战
2017/04/01 Javascript
vue使用iframe嵌入网页的示例代码
2020/06/09 Javascript
js+css实现打字效果
2020/06/24 Javascript
jQuery实现图片上传预览效果功能完整实例【测试可用】
2018/05/28 jQuery
微信小程序仿朋友圈发布动态功能
2018/07/15 Javascript
基于JavaScript伪随机正态分布代码实例
2019/11/07 Javascript
Python创建xml的方法
2015/03/10 Python
Python随机数用法实例详解【基于random模块】
2017/04/18 Python
pandas重新生成索引的方法
2018/11/06 Python
python3.6数独问题的解决
2019/01/21 Python
对Django中内置的User模型实例详解
2019/08/16 Python
Django模板语言 Tags使用详解
2019/09/09 Python
python命令 -u参数用法解析
2019/10/24 Python
Python3爬虫里关于代理的设置总结
2020/07/30 Python
python 监控logcat关键字功能
2020/09/04 Python
我的画教学反思
2014/04/28 职场文书
个人政风行风自查自纠报告
2014/10/21 职场文书
承兑汇票转让证明怎么写?
2014/11/30 职场文书
社会主义核心价值观主题教育活动总结
2015/05/07 职场文书
党性教育心得体会(共6篇)
2016/01/21 职场文书
go语言中GOPATH GOROOT的作用和设置方式
2021/05/05 Golang
SQL Server实现分页方法介绍
2022/03/16 SQL Server
《战锤40K:暗潮》跳票至9月 公布新宣传片
2022/04/03 其他游戏