Vue 固定头 固定列 点击表头可排序 表格组件
原理是将原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 = ["品类", "产品种类", "均价", "销量", "销量环比", "销量占比", "销额(万元)", "销额环比", "销额占比", "评论总数", "好评率"] } }
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: C# 实现设置系统环境变量设置
- 下一篇: C# 环境变量的配置