基础使用
- 滚动分页模式;leftRollScroll 是一个函数返回当前分页信息
高度计算的话,是获取咱们组件的父级的clientHeight,然后减去这个父级内除了表格的高度。例如:
initTableHeight() {
this.$nextTick(() =>
setTimeout(() => {
const setFn = (key, thisKey) => {
this[thisKey] = this.$refs[key].clientHeight;
};
[
"left_table_box,leftTH",
"rlt_table_box,rltTH",
"rlb_table_box,rlbTH",
"rr_table_box,rrTH",
].forEach((item) => setFn(...item.split(",")));
}, 0)
);
},
1. lh-table组件代码:
- 下面两点都是分页的代码,可以用自己分页组件替换掉它。 具体替换请看本文的 2.1 lh-table组件这块是去掉分页组件的table组件封装,但是里面功能没有以下的全。
- 分页组件可以直接用element-ui的分页组件,但是table组件内涉及分页的得换一换
<template>
<div class="lh-table" v-loading="loadings">
<el-table
ref="LHTable"
border
:class="['table-msg color-table ', className]"
:stripe="stripe"
:highlight-current-row="highlight"
:size="size"
:data="tableDataCheck"
:max-height="height"
:row-class-name="rowClassName"
:style="{ height: pageination ? 'calc(100% - 60px)' : '100%' }"
:span-method="spanMethod"
@cell-dblclick="(param) => $emit('cell-dblclick', param)"
@cell-click="(param) => $emit('cell-click', param)"
@selection-change="(param) => $emit('selection-change', param)"
>
<template
v-for="colConfig in tableConfig.filter(
(item) => item.lhDisplay !== 'none'
)"
>
<el-table-column
v-bind="colConfig"
align="center"
:key="colConfig['id']"
v-if="!colConfig.type"
>
<template slot="header" slot-scope="scope">
<render
v-if="colConfig.headerRender"
:render="colConfig.headerRender"
:row="scope.row"
:index="scope.$index"
:column="colConfig"
:key="colConfig['id']"
/>
<span v-else>{{ colConfig.label }}</span>
</template>
<template slot-scope="scope">
<render
v-if="colConfig.render"
:render="colConfig.render"
:row="scope.row"
:index="scope.$index"
:column="colConfig"
:key="colConfig['id']"
/>
<span v-else>{{
scope.row[colConfig && colConfig.prop] || "-"
}}</span>
</template>
</el-table-column>
<el-table-column v-else :key="colConfig['id']" v-bind="colConfig" align="center" />
</template>
</el-table>
<LhPageination
small
background
v-if="pageination"
:layout="pageLayout"
:page-size="pageSize"
:pageSizes="pageSizes"
:current-page="currentPage"
:total="totalNum"
@current-change="handleCurrentChange"
@size-change="handleSizeChange"
/>
</div>
</template>
<script>
import LhPageination from "@/components/anHui-new/LhPagination/index.js";
const pageination = {
currentPage: 1,
totalNum: 0,
pageSize: 30,
pageSizes: [10, 15, 20, 30, 50, 100],
};
const render = {
functional: true,
props: {
row: Object,
render: Function,
index: Number,
column: {
type: Object,
default: null,
},
},
render: (h, data) => {
const params = {
row: data.props.row,
index: data.props.index,
};
if (data.props.column) params.column = data.props.column;
return data.props.render(h, params);
},
};
export default {
name: "LhTable",
props: {
tableConfig: {
type: Array,
default: () => [
{
label: "序号",
type: "index",
width: "80px",
},
{
label: "名字",
prop: "name",
},
{
label: "公司名称",
prop: "cmyName",
},
],
},
p_tableInfo: {
type: Object,
default: () => ({
tableData: [],
loading: false,
}),
},
p_pageinationInfo: {
type: Object,
default: () => pageination,
},
height: {
type: Number,
default: 250,
},
pageination: {
type: Boolean,
default: true,
},
size: {
type: String,
default: "small",
},
highlight: {
type: Boolean,
default: true,
},
className: {
type: String,
default: "",
},
stripe: {
type: Boolean,
default: true,
},
rowClassName: {
type: Function,
},
spanMethod: {
type: Function,
},
rollScroll: {
type: Function | Boolean,
default: false,
},
},
inject: {
pageinationInfo: {
default: () => ({
lh_spe_flag: true,
}),
},
tableInfo: {
default: () => ({
lh_spe_flag: true,
}),
},
},
watch: {
"pageinationInfo.totalNum"(n) {
this.totalNum = n;
},
"pageinationInfo.currentPage"(n) {
this.currentPage = n;
},
},
computed: {
loadings() {
return this.tableInfo.lh_spe_flag
? this.p_tableInfo.loading || false
: (this.tableInfo && this.tableInfo.loading) || false;
},
tableDataCheck() {
return this.tableInfo.lh_spe_flag
? this.p_tableInfo.tableData
: this.tableInfo.tableData;
},
pageinationInfoCheck() {
return this.pageinationInfo.lh_spe_flag
? this.p_pageinationInfo
: this.pageinationInfo;
},
},
components: {
LhPageination,
render,
},
data() {
const { currentPage, totalNum, pageSize, pageSizes, pageLayout } = this
.pageinationInfo.lh_spe_flag
? this.p_pageinationInfo
: this.pageinationInfo || pageination;
return {
pageLayout: pageLayout || [
["total", "sizes"],
["prev", "pager", "next", "jumper"],
],
currentPage,
totalNum,
pageSize,
pageSizes,
};
},
created() {
this.rollScroll && this.$nextTick(() => this.addRollListener());
},
methods: {
handleCurrentChange(v) {
this.$emit("current-change", v);
},
handleSizeChange(v) {
this.$emit("size-change", v);
},
addRollListener() {
const dom = this.$refs.LHTable.bodyWrapper;
dom.addEventListener("scroll", () => {
const { pageSize, currentPage, totalNum } = this.pageinationInfoCheck;
const all = pageSize * currentPage;
const scrollTop = dom.scrollTop;
const windowHeight = dom.clientHeight || dom.clientHeight;
const scrollHeight = dom.scrollHeight || dom.scrollHeight;
if (scrollTop + windowHeight + 1 > scrollHeight) {
if (all < totalNum) {
this.rollScroll(this.pageinationInfoCheck);
_.isBoolean(this.rollScroll) &&
this.$emit("roll-scroll", this.pageinationInfoCheck);
}
}
});
},
},
};
</script>
<style lang="less" scoped>
.lh-table {
position: relative;
height: 100%;
.table-msg {
position: absolute;
}
.el-pagination {
position: absolute;
bottom: 0;
}
/deep/.el-table__body-wrapper {
height: 100% !important;
.el-table__empty-block {
min-height: 10px !important;
}
}
}
</style>
2. LhPagination.js
- 其实就是element-ui的el-Pagination,但是我根据需求更改了一下样式配置;
import Pager from './pager.vue';
import Locale from 'element-ui/src/mixins/locale';
const valueEquals = (a, b) => {
if (a === b) return true;
if (!(a instanceof Array)) return false;
if (!(b instanceof Array)) return false;
if (a.length !== b.length) return false;
for (let i = 0; i !== a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
};
export default {
name: 'ElPagination',
props: {
pageSize: {
type: Number,
default: 10
},
small: Boolean,
total: Number,
pageCount: Number,
pagerCount: {
type: Number,
validator(value) {
return (value | 0) === value && value > 4 && value < 22 && (value % 2) === 1;
},
default: 7
},
currentPage: {
type: Number,
default: 1
},
layout: {
default: 'prev, pager, next, jumper, ->, total'
},
pageSizes: {
type: Array,
default() {
return [10, 20, 30, 40, 50, 100];
}
},
popperClass: String,
prevText: String,
nextText: String,
background: Boolean,
disabled: Boolean,
hideOnSinglePage: Boolean,
lhType: Boolean
},
data() {
return {
internalCurrentPage: 1,
internalPageSize: 0,
lastEmittedPage: -1,
userChangePageSize: false
};
},
render(h) {
const layout = this.layout;
if (!layout) return null;
if (this.hideOnSinglePage && (!this.internalPageCount || this.internalPageCount === 1)) return null;
const TEMPLATE_MAP = {
prev: <prev></prev>,
jumper: <jumper></jumper>,
pager: <pager currentPage={ this.internalCurrentPage } pageCount={ this.internalPageCount } pagerCount={ this.pagerCount } on-change={ this.handleCurrentChange } disabled={ this.disabled }></pager>,
next: <next></next>,
sizes: <sizes pageSizes={ this.pageSizes }></sizes>,
slot: <slot>{ this.$slots.default ? this.$slots.default : '' }</slot>,
total: <total></total>
};
const content = layout || [['total', 'sizes'],['prev', 'pager', 'next', 'jumper']];
let template = <div class={['el-pagination lh-pagination', this.lhType?'flex-jcenter':'flex-between', {
'is-background': this.background,
'el-pagination--small': this.small,
}] }>
{
content.map(item=>(
<div class='lh-flex'>
{
item.map(value=>(
TEMPLATE_MAP[value]
))
}
</div>
))
}
</div>;
const rightWrapper = <div class="el-pagination__rightwrapper"></div>;
let haveRightWrapper = false;
template.children = template.children || [];
rightWrapper.children = rightWrapper.children || [];
if (haveRightWrapper) {
template.children.unshift(rightWrapper);
}
return template;
},
components: {
Prev: {
render(h) {
return (
<button
type="button"
class="btn-prev"
disabled={ this.$parent.disabled || this.$parent.internalCurrentPage <= 1 }
on-click={ this.$parent.prev }>
{
this.$parent.prevText
? <span>{ this.$parent.prevText }</span>
: <i class="el-icon el-icon-arrow-left"></i>
}
</button>
);
}
},
Next: {
render(h) {
return (
<button
type="button"
class="btn-next"
disabled={ this.$parent.disabled || this.$parent.internalCurrentPage === this.$parent.internalPageCount || this.$parent.internalPageCount === 0 }
on-click={ this.$parent.next }>
{
this.$parent.nextText
? <span>{ this.$parent.nextText }</span>
: <i class="el-icon el-icon-arrow-right"></i>
}
</button>
);
}
},
Sizes: {
mixins: [Locale],
props: {
pageSizes: Array
},
watch: {
pageSizes: {
immediate: true,
handler(newVal, oldVal) {
if (valueEquals(newVal, oldVal)) return;
if (Array.isArray(newVal)) {
this.$parent.internalPageSize = newVal.indexOf(this.$parent.pageSize) > -1
? this.$parent.pageSize
: this.pageSizes[0];
}
}
}
},
render(h) {
return (
<div class="el-pagination__sizes">
每页显示 
<el-select
value={ this.$parent.internalPageSize }
popperClass={ this.$parent.popperClass || '' }
size="mini"
on-input={ this.handleChange }
disabled={ this.$parent.disabled }>
{
this.pageSizes.map(item =>
<el-option
value={ item }
label={ item }>
</el-option>
)
}
</el-select>
 条记录
</div>
);
},
methods: {
handleChange(val) {
if (val !== this.$parent.internalPageSize) {
this.$parent.internalPageSize = val = parseInt(val, 10);
this.$parent.userChangePageSize = true;
this.$parent.$emit('update:pageSize', val);
this.$parent.$emit('size-change', val);
}
}
}
},
Jumper: {
mixins: [Locale],
data() {
return {
userInput: null
};
},
watch: {
'$parent.internalCurrentPage'() {
this.userInput = null;
}
},
methods: {
handleKeyup({ keyCode, target }) {
if (keyCode === 13) {
this.handleChange(target.value);
}
},
handleInput(value) {
this.userInput = value;
},
handleChange(value) {
this.$parent.internalCurrentPage = this.$parent.getValidCurrentPage(value);
this.$parent.emitChange();
this.userInput = null;
}
},
render(h) {
return (
<span class="el-pagination__jump">
{ this.t('el.pagination.goto') }
<el-input
class="el-pagination__editor is-in-pagination"
min={ 1 }
max={ this.$parent.internalPageCount }
value={ this.userInput !== null ? this.userInput : this.$parent.internalCurrentPage }
type="number"
disabled={ this.$parent.disabled }
nativeOnKeyup={ this.handleKeyup }
onInput={ this.handleInput }
onChange={ this.handleChange }/>
{ this.t('el.pagination.pageClassifier') }
</span>
);
}
},
Total: {
mixins: [Locale],
render(h) {
return (
typeof this.$parent.total === 'number'
? <span class="el-pagination__total">总共 { this.$parent.total } 条记录</span>
: ''
);
}
},
Pager
},
methods: {
handleCurrentChange(val) {
this.internalCurrentPage = this.getValidCurrentPage(val);
this.userChangePageSize = true;
this.emitChange();
},
prev() {
if (this.disabled) return;
const newVal = this.internalCurrentPage - 1;
this.internalCurrentPage = this.getValidCurrentPage(newVal);
this.$emit('prev-click', this.internalCurrentPage);
this.emitChange();
},
next() {
if (this.disabled) return;
const newVal = this.internalCurrentPage + 1;
this.internalCurrentPage = this.getValidCurrentPage(newVal);
this.$emit('next-click', this.internalCurrentPage);
this.emitChange();
},
getValidCurrentPage(value) {
value = parseInt(value, 10);
const havePageCount = typeof this.internalPageCount === 'number';
let resetValue;
if (!havePageCount) {
if (isNaN(value) || value < 1) resetValue = 1;
} else {
if (value < 1) {
resetValue = 1;
} else if (value > this.internalPageCount) {
resetValue = this.internalPageCount;
}
}
if (resetValue === undefined && isNaN(value)) {
resetValue = 1;
} else if (resetValue === 0) {
resetValue = 1;
}
return resetValue === undefined ? value : resetValue;
},
emitChange() {
this.$nextTick(() => {
if (this.internalCurrentPage !== this.lastEmittedPage || this.userChangePageSize) {
this.$emit('current-change', this.internalCurrentPage);
this.lastEmittedPage = this.internalCurrentPage;
this.userChangePageSize = false;
}
});
}
},
computed: {
internalPageCount() {
if (typeof this.total === 'number') {
return Math.max(1, Math.ceil(this.total / this.internalPageSize));
} else if (typeof this.pageCount === 'number') {
return Math.max(1, this.pageCount);
}
return null;
}
},
watch: {
currentPage: {
immediate: true,
handler(val) {
this.internalCurrentPage = this.getValidCurrentPage(val);
}
},
pageSize: {
immediate: true,
handler(val) {
this.internalPageSize = isNaN(val) ? 10 : val;
}
},
internalCurrentPage: {
immediate: true,
handler(newVal) {
this.$emit('update:currentPage', newVal);
this.lastEmittedPage = -1;
}
},
internalPageCount(newVal) {
const oldPage = this.internalCurrentPage;
if (newVal > 0 && oldPage === 0) {
this.internalCurrentPage = 1;
} else if (oldPage > newVal) {
this.internalCurrentPage = newVal === 0 ? 1 : newVal;
this.userChangePageSize && this.emitChange();
}
this.userChangePageSize = false;
}
}
};
3.pager.vue
- element-ui的组件
<template>
<ul @click="onPagerClick" class="el-pager">
<li
:class="{ active: currentPage === 1, disabled }"
v-if="pageCount > 0"
class="number">1</li>
<li
class="el-icon more btn-quickprev"
:class="[quickprevIconClass, { disabled }]"
v-if="showPrevMore"
@mouseenter="onMouseenter('left')"
@mouseleave="quickprevIconClass = 'el-icon-more'">
</li>
<li
v-for="pager in pagers"
:key="pager"
:class="{ active: currentPage === pager, disabled }"
class="number">{{ pager }}</li>
<li
class="el-icon more btn-quicknext"
:class="[quicknextIconClass, { disabled }]"
v-if="showNextMore"
@mouseenter="onMouseenter('right')"
@mouseleave="quicknextIconClass = 'el-icon-more'">
</li>
<li
:class="{ active: currentPage === pageCount, disabled }"
class="number"
v-if="pageCount > 1">{{ pageCount }}</li>
</ul>
</template>
<script type="text/babel">
export default {
name: 'ElPager',
props: {
currentPage: Number,
pageCount: Number,
pagerCount: Number,
disabled: Boolean
},
watch: {
showPrevMore(val) {
if (!val) this.quickprevIconClass = 'el-icon-more';
},
showNextMore(val) {
if (!val) this.quicknextIconClass = 'el-icon-more';
}
},
methods: {
onPagerClick(event) {
const target = event.target;
if (target.tagName === 'UL' || this.disabled) {
return;
}
let newPage = Number(event.target.textContent);
const pageCount = this.pageCount;
const currentPage = this.currentPage;
const pagerCountOffset = this.pagerCount - 2;
if (target.className.indexOf('more') !== -1) {
if (target.className.indexOf('quickprev') !== -1) {
newPage = currentPage - pagerCountOffset;
} else if (target.className.indexOf('quicknext') !== -1) {
newPage = currentPage + pagerCountOffset;
}
}
if (!isNaN(newPage)) {
if (newPage < 1) {
newPage = 1;
}
if (newPage > pageCount) {
newPage = pageCount;
}
}
if (newPage !== currentPage) {
this.$emit('change', newPage);
}
},
onMouseenter(direction) {
if (this.disabled) return;
if (direction === 'left') {
this.quickprevIconClass = 'el-icon-d-arrow-left';
} else {
this.quicknextIconClass = 'el-icon-d-arrow-right';
}
}
},
computed: {
pagers() {
const pagerCount = this.pagerCount;
const halfPagerCount = (pagerCount - 1) / 2;
const currentPage = Number(this.currentPage);
const pageCount = Number(this.pageCount);
let showPrevMore = false;
let showNextMore = false;
if (pageCount > pagerCount) {
if (currentPage > pagerCount - halfPagerCount) {
showPrevMore = true;
}
if (currentPage < pageCount - halfPagerCount) {
showNextMore = true;
}
}
const array = [];
if (showPrevMore && !showNextMore) {
const startPage = pageCount - (pagerCount - 2);
for (let i = startPage; i < pageCount; i++) {
array.push(i);
}
} else if (!showPrevMore && showNextMore) {
for (let i = 2; i < pagerCount; i++) {
array.push(i);
}
} else if (showPrevMore && showNextMore) {
const offset = Math.floor(pagerCount / 2) - 1;
for (let i = currentPage - offset ; i <= currentPage + offset; i++) {
array.push(i);
}
} else {
for (let i = 2; i < pageCount; i++) {
array.push(i);
}
}
this.showPrevMore = showPrevMore;
this.showNextMore = showNextMore;
return array;
}
},
data() {
return {
current: null,
showPrevMore: false,
showNextMore: false,
quicknextIconClass: 'el-icon-more',
quickprevIconClass: 'el-icon-more'
};
}
};
</script>
<style lang="less" scoped>
</style>
|