vue实现表格组件,带分页
最近因为项目需要,利用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实现表格组件,带分页相关推荐
- 顶级好用的 5 款 Vue table 表格组件测评与推荐
本文首发:<顶级好用的 5 款 Vue table 表格组件测评与推荐 - 卡拉云> Vue table 表格组件作为绝大多数项目需要内嵌的组件,可谓十分重要.表格看起来虽简单,实则坑很深 ...
- vxe-input vue 日期选择组件带农历节日、小圆点提醒
vxe-table vxe-input vue 日期选择组件带农历节日.小圆点提醒 默认的日期选择是没有节日信息的 可以通过 festival-method 方法自定义节日信息,接收一个对象,用于渲染 ...
- ant design vue table表格组件实现隔行变色
ant design vue table表格组件实现隔行变色 一.使用方法 html代码: <a-table:columns="patient":data-source=&q ...
- Ant Design Vue list表格组件
文章目录 1.案例部分代码 2. 简述 3.案例代码 1.案例部分代码 <a-table:columns="columns":row-key="record =&g ...
- vue 嵌套表格组件_使用form-create动态生成vue自定义组件和嵌套表单组件
使用form-create动态生成vue自定义组件和嵌套表单组件 maker.create 通过建立一个虚拟 DOM的方式生成自定义组件 生成 Maker let rule = [ formCreat ...
- vue 嵌套表格组件_vue+element中表格嵌套怎么做?
用的vue+element,现在需要做下面的东西,就是把下面的数据显示到el-table里 这是数据 [ { "productId": 3215, "productNam ...
- vue Element-ui 表格自带筛选框自定义高度
el-table中可以在一行的某列进行筛选,代码如下: <el-table-column prop="classOfTest" class="test" ...
- ant vue 树形菜单横向显示_丝滑般 Vue 拖拽排序树形表格组件Vue-DragTreeTable
今天给小伙伴们分享一款纵享丝滑般体验的Vue拖拽树形表格DragTreeTable. vue-drag-tree-table 基于vue.js实现可拖拽排序的树形表格组件.支持拖拽排序.固定表头.拖拽 ...
- React Table 表格组件使用教程 排序、分页、搜索过滤筛选功能实战开发
React Table 表格组件使用教程 react-table 安装和使用 React Table 表格排序功能 React Table 表格搜索过滤筛选功能 React Table 表格分页功能 ...
最新文章
- easyui的datagrid
- python request-urllib.request
- ip登录打印机怎么打印_不要打印,登录。
- 1.7 编程基础之字符串 30 字符环 python
- %12d在c语言中的意思,《C语言程序设计》习题.doc
- java重入锁 自旋锁_java 自旋锁(可重入且无死锁)
- Go 字典(Map)
- 网宿科技:向云服务商转型
- McAfee Endpoint Security安装失败排查步骤
- iOS之healthKit
- MySQL全文索引:中文语义分词检索
- 【HTML5】input标签中的Require必填项
- Ncurses学习经历(九)屏幕操作
- 索尼a7c语言没有英语,索尼A7C的三大优点和缺点,看完再决定要不要买
- 2021 部分团队的年终总结
- Spoon软件运行时点击右键程序无响应的解决方法
- win10系统修改电脑 hosts 地址
- 网页里面的空格的代码怎么写
- 百度APP视频播放中的解码优化
- 抖音一个好的标题让你轻松上热门,该怎么写好抖音标题。
热门文章
- Debian 和Ubuntu Mono 3.0 部署包
- iframe 的一点经历
- SharePoint Calendar Webparts
- 北京林大计算机科技应为abc哪类,北京林业大学新生入学要准备什么?
- mysql怎么使用sql语句查看表的编码_MySQL中使用SQL语句查看某个表的编码
- rideo选中 vue_适用于 Vue 的播放器组件Vue-Video-Player操作
- windows修改策略后执行命令_Windows 下的提权大合集
- sql网站路径php,如何在源码中找出sql语句的位置呢
- java星际小战_首届中国星际战队联赛:TSG夺冠,小hero刘建宏大战惊天地泣鬼神...
- c语言使用指针改数组逆置,用指针作函数参数,编写函数,将一个整型数组中的元素全部逆置。...