最近因为项目需要,利用vue开发了一套利于扩展的表格组件,可选择分页展示,带有排序功能支持,支持自定义操作按钮与class以及自定义render渲染。效果如下:

点击在线体验

使用简单:

html:

vue实例中传入基本的列信息:

完整代码:

<html><head><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script src="http://code.jquery.com/jquery-1.4.1.min.js"></script><style>table { width: 100%; margin-bottom: 24px; border-collapse: collapse; border-spacing: 0; empty-cells: show; border: 1px solid #e9e9e9;}table th { font: bold 14px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;background: #CAE8EA; color: #5c6b77; font-weight: 600; white-space: nowrap; border-top: 1px solid #C1DAD7;}table td, table th { padding: 8px 16px; text-align: left;border-right: 1px solid #C1DAD7; border-bottom: 1px solid #C1DAD7;}table th a { display: inline-block; margin: 0 4px; cursor: pointer;}table th a.on {color: #3399ff;}table th a:hover {color: #3399ff;}.row{display: flex;-ms-flex-wrap: wrap; flex-wrap: wrap; margin-right: -12px; margin-left: -12px;}.row .col-4{ -webkit-box-flex: 0; -ms-flex: 0 0 33.33333%; flex: 0 0 33.33333%; max-width: 20%;    position: relative; width: 100%; padding-right: 12px; padding-left: 12px;}.pagination{list-style: none;display: -webkit-box;display: -ms-flexbox;border-radius: .25rem;}.col-4{-webkit-box-flex: 0;flex: 0 0 33.33333%;max-width: 20%;}.pagination-sm{margin: 0;}button{outline: none;}.pagination-sm .page-link{padding: .25rem .5rem;font-size: .74375rem;line-height: 1.5;margin: 0;}.pagination-sm .active .page-link{color: red;}.btn-confirm {position: absolute; top: 50%; left: 70%; transform: translate(-50%, -50%); width: 80px; height: 30px; line-height: 20px; text-align: center; color: #fff;text-transform: uppercase; text-decoration: none; font-family: sans-serif; box-sizing: border-box; background: linear-gradient(90deg, #03a9f4, #f441a5, #ffeb3b, #03a9f4); background-size: 400%; border-radius: 60px; z-index: 1; }.btn-confirm:hover { animation: animate 8s linear infinite; } @keyframes animate { 0% { background-position: 0%; } 100% { background-position: 400%; } } .btn-confirm::before { content: ''; position: absolute; top: -5px; left: -5px; right: -5px; bottom: -5px; z-index: -1; background: linear-gradient(90deg, #03a9f4, #f441a5, #ffeb3b, #03a9f4); background-size: 400%; border-radius: 40px; opacity: 0; transition: 0.5s; }.btn-confirm:hover::before { filter: blur(20px); opacity: 1; animation: animate 8s linear infinite; } </style></head><body><div id="app"><tt-table :datas="datas" :columns="columns" pageSize=2 :rows="rows"></tt-table></div><script>
/**分页组件嵌入到表格中*/
Vue.component('page-split', {props: {totalRows: {required: true,type: Number},pageSize: {type: Number,default: 8},pageNumAmount: {type: Number,default: 3},pageNum: {type: Number,default: 1}},model: {prop: 'pageNum',event: 'switch-page'},data: function data() {return {totalPage: 0,inputPage: '',showPageList: []};},created: function() {this.calShowPageNums();},watch: {totalRows: function totalRows() {this.calShowPageNums();}},methods: {invokeAjaxMethod: function(){this.$emit('switch-page', this.pageNum);this.calShowPageNums();},toSpecialPage: function toSpecialPage() {if (!/^\d{1,10}$/.test(this.inputPage)) {this.inputPage = '';return false;}if (this.inputPage > this.totalPage || this.inputPage < 1) {this.inputPage = '';return false;}this.pageNum = this.inputPage;this.invokeAjaxMethod();},prePage: function prePage() {if (this.pageNum < 2) {return false;}this.pageNum--;this.invokeAjaxMethod();},goPage: function goPage(pageNo) {this.pageNum = pageNo;this.invokeAjaxMethod();},nextPage: function nextPage() {if (this.pageNum == this.totalPage) {return false;}this.pageNum++;this.invokeAjaxMethod();},//计算应该展示出的页号calShowPageNums: function calShowPageNums() {this.totalPage = this.getNumMultiple(this.totalRows, this.pageSize);var showPageNum = 1,showListIndex = 0;if (this.totalPage > this.pageNumAmount) {showPageNum = this.pageNum - (this.pageNumAmount >> 1); //显示的第一个页号if (this.totalPage - showPageNum < this.pageNumAmount) {//末尾几页页号数不够的时候showPageNum = this.totalPage - this.pageNumAmount + 1;}showPageNum = showPageNum < 1 ? 1 : showPageNum;}this.showPageList = []; //先清空原来的数据for (var currentNum = 0; currentNum < this.pageNumAmount; ++currentNum, showPageNum++) {if (showPageNum > this.totalPage) {break;}this.showPageList[showListIndex++] = showPageNum;}if (this.pageNum > this.totalPage && this.pageNum > 1){//删除最后一页的最后一条数据后,pageNum需要更改过来if (this.totalPage > 0) {this.pageNum = this.totalPage;this.invokeAjaxMethod();} else {//删除了所有数据this.pageNum = 0;}}},getNumMultiple(rawNum, baseNum, greedy = true) {var muti = parseInt(rawNum / baseNum);if (greedy && rawNum % baseNum > 0) {muti++;}return muti;}},template:'<div class="row">' +'<div class="col-4">' +'<div class="dataTables_info">共{{totalRows}}条记录</div>' +'</div>' +'<div class="col-4" style="white-space: nowrap;">' +'<nav aria-label="..." class="float-right">' +'<ul class="pagination pagination-sm">' +'<li class="page-item">' +'<button :class="pageNum <= 1 ? \'btn-disabled\': \'\'" class="page-link" @click="prePage()">上一页</button>' +'</li>' +'<li v-for="pageItemNo in showPageList" class="page-item" :class="pageItemNo == pageNum ? \'active\': \'\'">' +'<a class="page-link" @click="goPage(pageItemNo)" href="javascript:void(0)">{{pageItemNo}}<span class="sr-only"></span></a>' +'</li>' +'<li class="page-item">' +'<button :class="pageNum >= totalPage ? \'btn-disabled\' : \'\'" class="page-link" @click="nextPage()">下一页</button>' +'</li>' +'<span style="line-height: 27px;">共{{totalPage}}页</span>' +'</ul>' +'</nav>' +'</div>' +'<div class="col-4">' +'<div style="display: inline-flex;">' +'<label style="line-height: 27px;">到第</label>' +'<input v-model="inputPage" class="form-control form-control-sm" type="text" style="width: 80px;" maxlength="10"/>' +'<label style="line-height: 27px;">页</label>' +'<button style="height: 30px;line-height: 15px;" @click="toSpecialPage" class="btn btn-confirm">确定</button>' +'</div>' +'</div>' +'</div>'
});//单元格组件Vue.component('table-column', {props: {label: {//td展示的内容default: ""},view: {//是否展示type: Boolean,default: true},render: {type: Function},item: {type: Object,required: true}},data(){return {itemStyle: ''}},created() {if (!this.view && "undefined" != typeof this.view) {this.itemStyle += "display: none";}},render(h) {const that = this;if (that.render){return that.render(h, that.item);}return h("td", {style: that.itemStyle,class: 'table-td',domProps: {innerHTML:that.label}});}
});//操作按钮组件Vue.component('table-button', {props: {item: {//该条内容type: Object,required: true}},data(){return {cls: this.item.cls,label: this.item.label}},created(){if (!this.cls) {this.cls = "btn btn-outline-info btn-sm"}},methods: {clickEvt(){this.$emit("handel-click", this.item);}},template: `<button v-text="label" :class="cls" @click="clickEvt"></button>`
});//表格组件Vue.component("tt-table", {props: {pageSize: {type: Number,default: 2},rows: {//总数量default: 0},pageNo: {//当前页type: Number,default: 1},paging: {default: true},datas: {type: Array,required: true},columns: {type: Array,required: true}},data(){return {needPaging: this.paging,showList: []//当前页展示的内容}},created(){if (this.needPaging == "false"){this.needPaging = false;//转换成boolean} else {if (this.needPaging && this.needPaging != "true"){this.needPaging = true;}}this.handlePaging(1);},render(h){const that = this;var cols = new Array();var heads = new Array();//组装columnthat.columns.forEach((item, index) => {var colWidth = item.width;if (!colWidth) {colWidth = "15%";}let columnStyle = {width: colWidth};if (!item.view && typeof item.view != "undefined"){columnStyle.display = "none";}cols.push(h("col", {style: columnStyle}));if (item.sort){heads.push(h("th", {style: columnStyle}, [h("label", item.label),h("span", {on: {click: function(){that.handleOrder(item.code, true);}}}, "↑"),h("span", {on: {click: function(){that.handleOrder(item.code, false);}}}, "↓")]));} else {heads.push(h("th", {style: columnStyle}, item.label));}});var tbodys = new Array();that.showList.forEach((item, index) =>{var tds = new Array();that.columns.forEach((columnItem, columnIndex) =>{if (columnItem.code == 'opt') {//组装操作按钮let optBtns = [];columnItem.datas.forEach((btnItem) => {optBtns.push(h("table-button", {props: {item: btnItem},on: {'handel-click': function(obj){btnItem.clickHander(obj);}}}));});tds.push(h("td",{props:{label: ""}}, optBtns));} else {tds.push(h("table-column", {props: {label: item[ columnItem.code ],item: item,render: columnItem.render,view: columnItem.view//是否展示}}));}});tbodys.push(h("tr", tds));});if (that.needPaging) {return h("div", [h("div", {class: "table-responsive",style: "margin-top: 10px;"}, [h("table", {class: "table mb-0 table-striped"}, [h("colgroup", cols),h("thead", [h('tr', heads)]),h("tbody", tbodys)])]),h("page-split", {props: {totalRows: window.parseInt( that.rows ),pageNum: that.pageNo,pageSize: that.pageSize},domProps: {pageNum: that.pageNo,},on: {'switch-page': function(thisPage){that.pageNo = thisPage;that.handlePaging(thisPage);}}})]);} else {return h("div", {class: "table-responsive",style: "margin-top: 10px;"}, [h("table", {class: "table mb-0 table-striped"}, [h("colgroup", cols),h("thead", [h('tr', heads)]),h("tbody", tbodys)])]);}},methods: {/*** 处理排序*/handleOrder(sortedCode, isAsc){//如果是数字或者时间则按照大小排序,字符串则按照长短进行排序//找出一个非空的列var firstSortVal = '';for (let key in this.showList) {if (this.showList[key][sortedCode]) {firstSortVal = this.showList[key][sortedCode];break;}}if (!firstSortVal) {return false;}//判断类型var columnType = 0;//0-2分别标识string,number,date类型if (typeof window.parseFloat(firstSortVal) == "number") {columnType = 1;} else {let tempDate = new Date(firstSortVal);if (tempDate instanceof Date) {columnType = 2;}}var sortedFunction = '';switch (columnType){case 0:if (isAsc) {sortedFunction = function(a, b){return a[sortedCode].length < b[sortedCode].length ? -1 : 1;}} else {sortedFunction = function(a, b){return a[sortedCode].length > b[sortedCode].length ? -1 : 1;}}break;case 1:if (isAsc) {sortedFunction = function(a, b){return window.parseFloat(a[sortedCode]) < window.parseFloat(b[sortedCode]) ? -1 : 1;}} else {sortedFunction = function(a, b){return window.parseFloat(a[sortedCode]) > window.parseFloat(b[sortedCode]) ? -1 : 1;}}break;case 2:if (isAsc) {sortedFunction = function(a, b){return new Date( a[sortedCode] ) < new Date( b[sortedCode] ) ? -1 : 1;}} else {sortedFunction = function(a, b){return new Date( a[sortedCode] ) > new Date( b[sortedCode] ) ? -1 : 1;}}break;}this.showList.sort(sortedFunction);},/**处理分页*/handlePaging(pageNo){var showList = this.datas.slice((pageNo -1) * this.pageSize, pageNo * this.pageSize);this.showList = [].concat(showList);}}
});//挂载实例:
new Vue({el: "#app",data: {label: "hello world from vue inst",rows: 0,columns: [{code: "id",label: "ID",sort: true},{code: "name",label: "姓名",render: function(h, item){const that = this;return h({template: "<td>" + that.label + "</td>"});}},{code: "age",label: "年龄"},{code: "opt",label: "操作",datas: [{label: "查看",cls: 'class',clickHander(item){window.alert("click view:" + JSON.stringify(item));}},{label: "编辑",cls: 'class',clickHander(item){window.alert("click edit:" + JSON.stringify(item));}}]}],datas: [{id: "1",name: "name1",age: 21},{id: "2",name: "name2",age: 22},{id: "3",name: "name3",age: 33},{id: "4",name: "name4",age: 44},{id: "5",name: "name5",age: 55},{id: "6",name: "name6",age: 66}]},created(){this.rows = this.datas.length;}});</script></body>
</html>

vue实现表格组件,带分页相关推荐

  1. 顶级好用的 5 款 Vue table 表格组件测评与推荐

    本文首发:<顶级好用的 5 款 Vue table 表格组件测评与推荐 - 卡拉云> Vue table 表格组件作为绝大多数项目需要内嵌的组件,可谓十分重要.表格看起来虽简单,实则坑很深 ...

  2. vxe-input vue 日期选择组件带农历节日、小圆点提醒

    vxe-table vxe-input vue 日期选择组件带农历节日.小圆点提醒 默认的日期选择是没有节日信息的 可以通过 festival-method 方法自定义节日信息,接收一个对象,用于渲染 ...

  3. ant design vue table表格组件实现隔行变色

    ant design vue table表格组件实现隔行变色 一.使用方法 html代码: <a-table:columns="patient":data-source=&q ...

  4. Ant Design Vue list表格组件

    文章目录 1.案例部分代码 2. 简述 3.案例代码 1.案例部分代码 <a-table:columns="columns":row-key="record =&g ...

  5. vue 嵌套表格组件_使用form-create动态生成vue自定义组件和嵌套表单组件

    使用form-create动态生成vue自定义组件和嵌套表单组件 maker.create 通过建立一个虚拟 DOM的方式生成自定义组件 生成 Maker let rule = [ formCreat ...

  6. vue 嵌套表格组件_vue+element中表格嵌套怎么做?

    用的vue+element,现在需要做下面的东西,就是把下面的数据显示到el-table里 这是数据 [ { "productId": 3215, "productNam ...

  7. vue Element-ui 表格自带筛选框自定义高度

    el-table中可以在一行的某列进行筛选,代码如下: <el-table-column prop="classOfTest" class="test" ...

  8. ant vue 树形菜单横向显示_丝滑般 Vue 拖拽排序树形表格组件Vue-DragTreeTable

    今天给小伙伴们分享一款纵享丝滑般体验的Vue拖拽树形表格DragTreeTable. vue-drag-tree-table 基于vue.js实现可拖拽排序的树形表格组件.支持拖拽排序.固定表头.拖拽 ...

  9. React Table 表格组件使用教程 排序、分页、搜索过滤筛选功能实战开发

    React Table 表格组件使用教程 react-table 安装和使用 React Table 表格排序功能 React Table 表格搜索过滤筛选功能 React Table 表格分页功能 ...

最新文章

  1. easyui的datagrid
  2. python request-urllib.request
  3. ip登录打印机怎么打印_不要打印,登录。
  4. 1.7 编程基础之字符串 30 字符环 python
  5. %12d在c语言中的意思,《C语言程序设计》习题.doc
  6. java重入锁 自旋锁_java 自旋锁(可重入且无死锁)
  7. Go 字典(Map)
  8. 网宿科技:向云服务商转型
  9. McAfee Endpoint Security安装失败排查步骤
  10. iOS之healthKit
  11. MySQL全文索引:中文语义分词检索
  12. 【HTML5】input标签中的Require必填项
  13. Ncurses学习经历(九)屏幕操作
  14. 索尼a7c语言没有英语,索尼A7C的三大优点和缺点,看完再决定要不要买
  15. 2021 部分团队的年终总结
  16. Spoon软件运行时点击右键程序无响应的解决方法
  17. win10系统修改电脑 hosts 地址
  18. 网页里面的空格的代码怎么写
  19. 百度APP视频播放中的解码优化
  20. 抖音一个好的标题让你轻松上热门,该怎么写好抖音标题。

热门文章

  1. Debian 和Ubuntu Mono 3.0 部署包
  2. iframe 的一点经历
  3. SharePoint Calendar Webparts
  4. 北京林大计算机科技应为abc哪类,北京林业大学新生入学要准备什么?
  5. mysql怎么使用sql语句查看表的编码_MySQL中使用SQL语句查看某个表的编码
  6. rideo选中 vue_适用于 Vue 的播放器组件Vue-Video-Player操作
  7. windows修改策略后执行命令_Windows 下的提权大合集
  8. sql网站路径php,如何在源码中找出sql语句的位置呢
  9. java星际小战_首届中国星际战队联赛:TSG夺冠,小hero刘建宏大战惊天地泣鬼神...
  10. c语言使用指针改数组逆置,用指针作函数参数,编写函数,将一个整型数组中的元素全部逆置。...