分享一款自己写的table组件 用起来还算简单好用 (先介绍使用方法(ts版本的))
引入组件不多说
import jTable from '../comp/comp/table/table.vue';//table
@Component({
components: {
jTable,
},
})
页面使用
<j-table ref = "jtable" :tableOpt = "tableOpt"></j-table>
重点!!!!
表格的配置
tableOpt:object = { /** * @desc 表格数据来源请求(ajax地址) */ getUrl:function(){ return "/api/gettable" }, /** * @description 页码配置 * @example * index : number 开始页码 * pageSize : number 每页多少条 * indexKey : string 后台接口接受开始页码的key名 * pageSizeKey : string 后台接口接受每页多少条的key名 */ pageOption:{ index:5 , pageSize:1, indexKey:"index", pageSizeKey:"pageSize" }, /** * @description 数据处理函数 用于处理后台返回的数据 需要返回一个json * data : array 包含一个json的数组,数据源 * index : number 当前页码 * total : number 总条数码 * totalPage : number 总页码数 */ dataHandle(data:any){ return { data:data.rows, index:data.index, total:data.total, totalPage:data.totalPage, } }, /** * @description 表格中每一列的名字和需要取key值 */ titleMap:[ { name:"名字", key:"name", }, { name:"年龄", key:"age" }, { name:"手机号", key:"phone" }, { name:"年份", key:"year", }, { name:"月份", key:"month", }, { name:"月份", key:"month", }, { name:"日", key:"day", }, { name:"t", key:"t", }, { name:"z", key:"z", } ], /** * @description 表格按钮 * val : string 按钮文字 * callback : function 按钮回掉函数(包含整行数据) * type : 按钮的类型 详情看button组件 * threed 按钮是否是3d的 * text 按钮是否是文字形的 */ actions:[ { val:"操作1", callback:this.ccc, type:"primary", threed : false, text:false, }, { val:"操作2", callback:this.ddd, type:"primary", threed : true, text:false, }, { val:"操作3", callback:this.ddd, type:"warning", threed : true, text:true, } ] }
就是这么简单 不过需要引入我的button组件 稍后补充下button组件的使用 感觉秒杀element使用
接下来上table代码
<template> <div> <table class = "j-table-box" cellspacing="0" cellpadding="0"> <table-header :titleMap = "state.titleMap" :actions = "state.actions"></table-header> <table-body :data = "state.tableRows" :titleMap = "state.titleMap" :actions = "state.actions"></table-body> </table> <table-page :page = "state.tableInfo" :pkey = "$data.__key"></table-page> </div> </template> <script lang="ts"> /** * tableoptions interface */ interface tableOpt { getUrl:Function; pageOption:{ indexKey:string; index:number; pageSizeKey:string; pageSize:number; }; dataHandle:Function, titleMap:number[], actions:number[], } /** * tableArr interface */ interface tableArr { data:number[], total:number, index:number totalPage:number, } import { Vue, Component,Prop, Provide,} from 'vue-property-decorator'; import tableHeader from "./tableHeader.vue"; import tableBody from "./tableBody.vue"; import tablePage from "./tablePage.vue"; import Fetch from "../../tool/fetch"; import Key from "../../tool/compConfig" function settableData(data:tableArr,that: any):void{ that.state.tableRows = data.data; that.state.tableInfo.total = data.total; that.state.tableInfo.totalPage = data.totalPage; that.state.tableInfo.index = data.index; } @Component({ components:{ tableHeader, tableBody, tablePage }, }) export default class jTable extends Vue{ @Prop() tableOpt !:tableOpt; state = { tableInfo : { pageSize:this.tableOpt.pageOption.pageSize, index:this.tableOpt.pageOption.index, total:0, totalPage:0, }, actions:this.tableOpt.actions ? this.tableOpt.actions : [], tableRows : [], titleMap:this.tableOpt.titleMap, } __key :number = Key.getKey(); mounted(){ var _this = this; this.$_event.$on(this.$data.__key+"TABLEEVENT",function(tag:any,...other:any[]):void{ if(!tag){ return ; } if(tag == "prePage"){ _this.renderTable(other[0]); } if(tag == "nextPage"){ _this.renderTable(other[0]); } if(tag == "appointPage"){ _this.renderTable(other[0]); } }) this.renderTable(); } beforeDestroy(){ this.$_event.$off("TABLEEVENT") } /** * @params {number} index 获取的页码 */ renderTable(index?:number):void{ if(!index){ index = this.state.tableInfo.index } if(this.tableOpt.getUrl()){ Fetch.getFetch(this.tableOpt.getUrl(),{ [this.tableOpt.pageOption.indexKey]:index, [this.tableOpt.pageOption.pageSizeKey]:this.state.tableInfo.pageSize }).then((data:any) => { let array = this.tableOpt.dataHandle(data); settableData(array,this); console.log(this,111); }) .catch(error => { console.log(error,2222); }) } } /** * @description 获取当前页数 */ getCurrentPage(){ return this.state.tableInfo.index } /** * 获取当前页数据 */ getCurrentPageData(){ return this.state.tableRows } } </script> <style lang="scss"> .j-table-box{ 100%; } </style>
<template> <tbody class = "j-table-body"> <tr v-for = "(row,rowKey) in data" :key = "rowKey"> <td v-if = "actions.length > 0"> <j-button v-for = "(config,index) in actions" :key = "index" inline :type = "config.type?config.type:'default'" :threed = "config.threed ? config.threed:false" :text = "config.text ? config.text:false" @click = "config.callback ? config.callback(row) : ''"> {{config.val ? config.val : '操作'}} </j-Button> </td> <td v-for = "(title,titleKey) in titleMap" :key = "titleKey"> {{ row[title.key] }} </td> </tr> </tbody> </template> <script lang = "ts"> import { Vue, Component,Prop, Provide,} from 'vue-property-decorator'; import jButton from "../button/button.vue"; @Component({ components:{ jButton } }) export default class jTableBody extends Vue{ @Prop({default:[]}) data ?:number[]; @Prop({default:[]}) titleMap ?:number[]; @Prop({default:[]}) actions ?:number[]; } </script> <style scoped> .j-table-body tr td { border:1px solid #aeaeae; text-align: center; } </style>
<template> <thead class = "j-table-header"> <tr> <th v-if = "actions.length > 0">操作</th> <th v-for = "(title,titleKey) in titleMap" :key = "titleKey"> {{ title.name }} </th> </tr> </thead> </template> <script lang = "ts"> import { Vue, Component,Prop, Provide,} from 'vue-property-decorator'; @Component({ }) export default class jTableHeader extends Vue{ @Prop({default:[]}) titleMap ?: number[]; @Prop({default:[],type:Array}) actions ?:number[]; } </script> <style scoped> .j-table-header tr th { border:1px solid #aeaeae; text-align: center; } </style>
<template> <div class = "j-table-page"> <ul class = "page-box"> <template v-if = "page.totalPage<=8"> <li class="page-btn" v-for = "(index,key) in page.totalPage" :class = "parseInt(page.index) == parseInt(index)?'current':'normal'" :key = "key" @click = "getPage(index)"> {{ index }} </li> </template> <template v-if = "page.totalPage > 8"> <li class="page-btn" v-for = "(index,key) in 2" :class = "parseInt(page.index) == parseInt(index)?'current':'normal'" :key = "'table_footer_start' + key" @click = "getPage(index)"> {{ parseInt(index) }} </li> <li class = "page-btn-ellipsis" v-show = 'page.index > 3' v-hover = "'<'" @click = "prePages(page.index-3)"> ... </li> <li class="page-btn normal" v-if = "parseInt(page.index)-1>3 && parseInt(page.index)-1<= page.totalPage-2" @click = "getPage(page.index-1)"> {{ page.index-1 }} </li> <li class="page-btn current" v-if = "parseInt(page.index)>2 && parseInt(page.index)<= page.totalPage-2" @click = "getPage(page.index)"> {{ page.index }} </li> <li class="page-btn normal" v-if = "parseInt(page.index)+1 <= page.totalPage-2 && parseInt(page.index)+1 > 2" @click = "getPage(page.index+1)"> {{ page.index+1 }} </li> <li class = "page-btn-ellipsis" v-show = 'parseInt(page.totalPage -3) > parseInt(page.index)' v-hover = "'>'" @click = "nextPages(page.index+3)"> ... </li> <li class="page-btn" v-for = "(index,key) in [1,0]" :class = "parseInt(page.totalPage) - parseInt(index) == page.index?'current':'normal'" :key = "'table_footer_last' + key" @click = "getPage(page.totalPage - index)"> {{ parseInt(page.totalPage) - parseInt(index) }} </li> </template> </ul> </div> </template> <script lang = "ts"> import { Vue, Component,Prop} from 'vue-property-decorator'; @Component({ }) export default class jTablePage extends Vue{ @Prop({default:[]}) page?:number[]; @Prop({}) pkey?:number[]; myThis:any = this; nextPages(page:number):void{ this.$_event.$emit(this.pkey + "TABLEEVENT","nextPage",page); } prePages(page:number):void{ this.$_event.$emit(this.pkey + "TABLEEVENT","prePage",page); } getPage(page:number):void{ this.$_event.$emit(this.pkey + "TABLEEVENT","appointPage",page); } } </script> <style scoped> .j-table-page{ 100%; text-align: center; padding-top:10px; } .j-table-page .page-box{ 50%; text-align:center; margin:0 auto; } .j-table-page .page-box .page-btn-ellipsis{ display:inline-block; list-style: none; margin-left: 10px; margin-right: 10px; vertical-align: top; cursor:pointer; } .j-table-page .page-box .page-btn{ 30px; height:30px; background:#efefef; box-shadow: 0px 0px 3px #aeaeae; border-radius:5px; display:inline-block; list-style: none; line-height: 30px; margin-left:5px; } .j-table-page .page-box .page-btn:hover{ background:#e5e5e5; cursor:pointer; } .page-btn.current{ background:rgb(141, 141, 240)!important; color:#fff; } </style>
<template> <div :class = "{'j__box__inline':inline}"> <button class = "j__btn" :class = "[ type ? 'j__button__'+type : 'j__button__default', { 'j__button__text':text, 'j__button__circle':circle, 'j__button__3D':threed }, ]" v-on="$listeners"> <slot/> </button> </div> </template> <script lang="ts"> import { Vue,Component,Prop,Provide } from "vue-property-decorator"; @Component({}) export default class jButton extends Vue { @Prop() type ?:string; @Prop({default:false,type:Boolean}) inline ?: boolean; @Prop({default:false,type:Boolean}) text ?: boolean; @Prop({default:false,type:Boolean}) circle ?: boolean; @Prop({default:false,type:Boolean}) threed ?: boolean; } </script> <style scoped> .j__box__inline{ display:inline; margin-left:5px; margin-right:5px; } .j__btn { cursor: pointer; /* 鼠标移入按钮范围时出现手势 */ outline: none; /* 不显示轮廓线 */ font-size: 12px; /* 字体大小 */ border:1px solid #efefef; box-sizing:border-box; padding:5px 10px; border-radius: 3px; } .j__button__3D{ transition-duration: .3s; margin-top:10px; margin-bottom:10px; } .j__button__default { background:#fff; color:#333; } .j__button__default:hover { background:#efefef; color:#444; } .j__button__default.j__button__3D{ border:none!important; -webkit-box-shadow: 0 7px 0 #dbe5ec, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #dbe5ec, 0 8px 3px rgba(0, 0, 0, 0.3); } .j__button__default.j__button__3D:active{ transform: translate(0,5px); -webkit-box-shadow: 0 0 0 #dbe5ec, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #dbe5ec, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__text.j__button__default:hover{ color:#999!important; } .j__button__text.j__button__3D.j__button__default{ border:none!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__text.j__button__3D.j__button__default:hover{ border:none!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__text.j__button__3D.j__button__default:active{ transform: translate(0)!important; border:none!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__primary { background:#069af4; color:#fff; } .j__button__primary:hover { background:#47b0f7; color:#fff; } .j__button__primary.j__button__3D{ border:none!important; -webkit-box-shadow: 0 7px 0 #0880d7, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #0880d7, 0 8px 3px rgba(0, 0, 0, 0.3); } .j__button__text.j__button__primary:hover{ color:#069af4!important; } .j__button__text.j__button__3D.j__button__primary{ transform: translate(0)!important; border:none!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__primary.j__button__3D:hover{ background:#1194e6; } .j__button__primary.j__button__3D:active{ transform: translate(0,5px); -webkit-box-shadow: 0 0 0 #0880d7, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #0880d7, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__success { background:#a4de47; color:#fff; } .j__button__success:hover { background:#b8e56c; color:#fff; } .j__button__success.j__button__3D{ border:none!important; -webkit-box-shadow: 0 7px 0 #84b91f, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #84b91f, 0 8px 3px rgba(0, 0, 0, 0.3); } .j__button__success.j__button__3D:hover{ background:rgb(146, 204, 53); } .j__button__success.j__button__3D:active{ transform: translate(0,5px); -webkit-box-shadow: 0 0 0 #84b91f, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #84b91f, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__text.j__button__success:hover{ color:#a4de47!important; } .j__button__text.j__button__3D.j__button__success{ transform: translate(0)!important; border:none!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__warning { background:#ffae2d; color:#fff; } .j__button__warning:hover { background:#ffc056; color:#fff; } .j__button__warning.j__button__3D{ border:none!important; -webkit-box-shadow: 0 7px 0 #e59501, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #e59501, 0 8px 3px rgba(0, 0, 0, 0.3); } .j__button__warning.j__button__3D:active{ transform: translate(0,5px); -webkit-box-shadow: 0 0 0 #e59501, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #e59501, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__warning.j__button__3D:hover{ background:#f8a621; } .j__button__text.j__button__warning:hover{ color:#ffae2d!important; } .j__button__text.j__button__3D.j__button__warning{ transform: translate(0)!important; border:none!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__danger { background:#ff4356; color:#fff; } .j__button__danger:hover { background:#ff7680; color:#fff; } .j__button__danger.j__button__3D{ border:none!important; -webkit-box-shadow: 0 7px 0 #ff1022, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #ff1022, 0 8px 3px rgba(0, 0, 0, 0.3); } .j__button__danger.j__button__3D:active{ transform: translate(0,5px); -webkit-box-shadow: 0 0 0 #ff1022, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #ff1022, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__danger.j__button__3D:hover{ background:#ea3c4d; } .j__button__text.j__button__danger:hover{ color:#ff4356!important; } .j__button__text.j__button__3D.j__button__danger{ border:none!important; transform: translate(0)!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__info { background:#909399; color:#fff; } .j__button__info:hover { background:#a6a9ad; color:#fff; } .j__button__info.j__button__3D { border:none!important; -webkit-box-shadow: 0 7px 0 #7b7d85, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #7b7d85, 0 8px 3px rgba(0, 0, 0, 0.3); } .j__button__info.j__button__3D:hover{ background:#85888b; } .j__button__info.j__button__3D:active{ transform: translate(0,5px); -webkit-box-shadow: 0 0 0 #8a8c92, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #8a8c92, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__text.j__button__info:hover{ color:#909399!important; } .j__button__text.j__button__3D.j__button__info{ border:none!important; transform: translate(0)!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__remind { background:#7672e6; color:#fff; } .j__button__remind:hover { background:#a49eee; color:#fff; } .j__button__remind.j__button__3D{ border:none!important; -webkit-box-shadow: 0 7px 0 #5246e2, 0 8px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 7px 0 #5246e2, 0 8px 3px rgba(0, 0, 0, 0.3); } .j__button__remind.j__button__3D:hover{ background:#6560ec; } .j__button__remind.j__button__3D:active{ transform: translate(0,5px); -webkit-box-shadow: 0 0 0 #5246e2, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #5246e2, 0 0 0 rgba(0, 0, 0, 0.3); } .j__button__text.j__button__remind:hover{ color:#7672e6!important; } .j__button__text.j__button__3D.j__button__remind{ border:none!important; transform: translate(0)!important; -webkit-box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); box-shadow: 0 0 0 #7b7d85, 0 0 0 rgba(0, 0, 0, 0.3); } /* border类 */ .j__button__text{ border: 0px solid transparent!important; background:transparent!important; color:#333!important; margin:0!important; padding:0!important; } /* border radius 类 */ .j__button__circle{ border-radius:17px; } </style>
需要公用 js 文件
页面全局需要
import event from "./comp/tool/event";
Vue.use(event);
这是注册全局this.$event指令用于跨组件通信
/** * @description eventbus事件 * @author jinzz * created by 2018/05/25 * !!!取消事件订阅必须跟事件订阅成对出现,否则会重复订阅,对javascript性能造成不必要的浪费。因此B组件销毁前需取消当前事件订阅。 * @param {any} event 第一个参数是事件对象,第二个参数是接收到消息信息,可以是任意类型,更多参数也可以留作扩展,使用...运算符方便更多操作 * @method $on 事件订阅, 监听当前实例上的自定义事件。https://cn.vuejs.org/v2/api/#vm-on * @method $off 取消事件订阅,移除自定义事件监听器。 https://cn.vuejs.org/v2/api/#vm-off https://github.com/vuejs/vue/issues/3399 * @method $emit 事件广播, 触发当前实例上的事件。 https://cn.vuejs.org/v2/api/#vm-emit * @method $once 事件订阅, 监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器。 https://cn.vuejs.org/v2/api/#vm-once */ export default { install:function(Vue:any){ const eventHub = new Vue() Vue.prototype.$_event = { $on (...event:any[]) { eventHub.$on(...event) }, $off (...event:any[]) { eventHub.$off(...event) }, $once (...event:any[]) { eventHub.$emit(...event) }, $emit (...event:any[]) { eventHub.$emit(...event) } } } }
需要fetch.ts(用于ajax请求(我只写了get请求的,因为自己写着玩的,自己写的接口 所以只写了get))
import Q from "q"; interface jsonType { [key: string]: string } let defer = Q.defer(); let _active = { jsonToString(d:jsonType){ var result = "" for (let name in <object>d) { if (typeof d[name] != 'function') { result += "&" + name + "=" + encodeURIComponent(d[name]); } } return result.substring(1) } } // var _publishurl:string = "http://10.112.7.77:3000" // var _publishurl:string = "http://192.168.1.108:3000" var _publishurl:string = "http://172.20.10.2:3000" const getFetch = (url:string,params?:any)=> { return new Promise ((resolve,reject) => { let headers = { 'Content-Type': 'application/json; charset=UTF-8' }; let _opt = { method:"get", headers:headers } fetch(_publishurl + url + "?" + _active.jsonToString(params),_opt) .then((response) => { return response.json(); }) .then((data) => { resolve(data); }) .catch((error) => { reject(error); }) }) } export default { getFetch, }
最后还需要一个compConfig用于生成独立的key,保证页面多个组件不会找错
let __key:number = -1; export default { getKey(){ __key++; return __key; } }
到这基本就可以了
下面简单介绍button组件吧
使用方法:
inline :行内
circle : 圆角
threed : 3d
type : 类型
可选值
default
primary
success
warning
danger
info
remind
text : 文字
event事件 : 支持所有vue支持的
<j-button inline circle threed @click = "ccc" text>
补充 : table组件暴露出来的函数功能
获取当前页码
this.$refs.jtable.getCurrentPage()
获取当前页数据
this.$refs['jtable'].getCurrentPageData()
本人qq:421217189 又不明白的可以联系我