分享一款自己写的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 又不明白的可以联系我