Vue 固定头 固定列 点击表头可排序的表格组件
程序员文章站
2023-10-26 16:53:46
原理是将原table的指定行,指定列clone一份放在其上
实现代码如下:
原理是将原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 固定头 固定列 点击表头可排序的表格组件,希望对大家有所帮助
下一篇: 第四只锦盒