分享一款自己寫的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{
width: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{
width:100%;
text-align: center;
padding-top:10px;
}
.j-table-page .page-box{
width: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{
width: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 又不明白的可以聯系我
