diff --git a/examples/views/table/base/Basic.vue b/examples/views/table/base/Basic.vue index c5826743f..7f119c068 100644 --- a/examples/views/table/base/Basic.vue +++ b/examples/views/table/base/Basic.vue @@ -1,136 +1,472 @@ diff --git a/examples/views/table/scroll/ScrollFullRows.vue b/examples/views/table/scroll/ScrollFullRows.vue index 63d686e8a..c19bc54e4 100644 --- a/examples/views/table/scroll/ScrollFullRows.vue +++ b/examples/views/table/scroll/ScrollFullRows.vue @@ -34,7 +34,7 @@ :checkbox-config="{checkField: 'checked'}"> - + @@ -209,6 +209,7 @@ export default { const list = [] for (let index = 0; index < size; index++) { list.push({ + key: index, name: `名称${index}`, checked: false, sex: '0', @@ -225,6 +226,9 @@ export default { getSelectEvent () { const selectRecords = this.$refs.xTable.getCheckboxRecords() this.$XModal.alert(selectRecords.length) + }, + filterNameMethod ({ value, row }) { + return row.key > value } } } diff --git a/package.json b/package.json index 088906e5f..ae81e1878 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vxe-table", - "version": "3.4.14-beta.1", + "version": "3.4.14-beta.3", "description": "一个基于 vue 的 PC 端表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、贼灵活的配置项、扩展接口等...", "scripts": { "serve": "vue-cli-service serve", diff --git a/packages/filter/src/mixin.js b/packages/filter/src/mixin.js index 6e8a24c25..3d036cff5 100644 --- a/packages/filter/src/mixin.js +++ b/packages/filter/src/mixin.js @@ -159,7 +159,7 @@ export default { * @param {Event} evnt 事件 */ confirmFilterEvent (evnt) { - const { filterStore, filterOpts, scrollXLoad, scrollYLoad } = this + const { filterStore, filterOpts, scrollXLoad: oldScrollXLoad, scrollYLoad: oldScrollYLoad } = this const { column } = filterStore const { property } = column const values = [] @@ -175,19 +175,26 @@ export default { if (!filterOpts.remote) { this.handleTableData(true) this.checkSelectionStatus() - this.updateFooter() - if (scrollXLoad || scrollYLoad) { - this.refreshScroll() - if (scrollYLoad) { - this.updateScrollYSpace() - } - } } this.emitEvent('filter-change', { column, property, values, datas, filters: filterList, filterList }, evnt) this.closeFilter() - this.$nextTick(() => { - this.recalculate() + this.updateFooter().then(() => { + const { scrollXLoad, scrollYLoad } = this + if ((oldScrollXLoad || scrollXLoad) || (oldScrollYLoad || scrollYLoad)) { + if ((oldScrollXLoad || scrollXLoad)) { + this.updateScrollXSpace() + } + if ((oldScrollYLoad || scrollYLoad)) { + this.updateScrollYSpace() + } + return this.refreshScroll() + } + }).then(() => { this.updateCellAreas() + return this.recalculate(true) + }).then(() => { + // 存在滚动行为未结束情况 + setTimeout(() => this.recalculate(), 50) }) }, handleClearFilter (column) { diff --git a/packages/table/src/body.js b/packages/table/src/body.js index b3f187473..cbdb2b91e 100644 --- a/packages/table/src/body.js +++ b/packages/table/src/body.js @@ -3,7 +3,7 @@ import GlobalConfig from '../../v-x-e-table/src/conf' import VXETable from '../../v-x-e-table' import { UtilTools, DomTools, isEnableConf } from '../../tools' import { getOffsetSize, calcTreeLine, mergeBodyMethod, removeScrollListener, restoreScrollListener } from './util' -import { browse } from '../../tools/src/dom' +import { browse, setScrollLeftAndTop } from '../../tools/src/dom' const renderType = 'body' @@ -401,7 +401,7 @@ function renderRows (h, _vm, $xetable, fixedType, tableData, tableColumn) { * 同步滚动条 */ let scrollProcessTimeout -function syncBodyScroll (scrollTop, elem1, elem2) { +function syncBodyScroll (_vm, fixedType, scrollTop, elem1, elem2) { if (elem1 || elem2) { if (elem1) { removeScrollListener(elem1) @@ -412,9 +412,30 @@ function syncBodyScroll (scrollTop, elem1, elem2) { elem2.scrollTop = scrollTop } clearTimeout(scrollProcessTimeout) - scrollProcessTimeout = setTimeout(function () { + scrollProcessTimeout = setTimeout(() => { + const { tableBody, leftBody, rightBody } = _vm.$refs + const bodyElem = tableBody.$el + const leftElem = leftBody ? leftBody.$el : null + const rightElem = rightBody ? rightBody.$el : null restoreScrollListener(elem1) restoreScrollListener(elem2) + // 检查滚动条是的同步 + let targetTop = bodyElem.scrollTop + let targetLeft = bodyElem.scrollLeft + if (fixedType === 'left') { + if (leftElem) { + targetTop = leftElem.scrollTop + targetLeft = leftElem.scrollLeft + } + } else if (fixedType === 'right') { + if (rightElem) { + targetTop = rightElem.scrollTop + targetLeft = rightElem.scrollLeft + } + } + setScrollLeftAndTop(bodyElem, targetLeft, targetTop) + setScrollLeftAndTop(leftElem, targetLeft, targetTop) + setScrollLeftAndTop(rightElem, targetLeft, targetTop) }, 300) } } @@ -621,10 +642,10 @@ export default { } if (leftElem && fixedType === 'left') { scrollTop = leftElem.scrollTop - syncBodyScroll(scrollTop, bodyElem, rightElem) + syncBodyScroll($xetable, fixedType, scrollTop, bodyElem, rightElem) } else if (rightElem && fixedType === 'right') { scrollTop = rightElem.scrollTop - syncBodyScroll(scrollTop, bodyElem, leftElem) + syncBodyScroll($xetable, fixedType, scrollTop, bodyElem, leftElem) } else { if (isRollX) { if (headerElem) { @@ -637,7 +658,7 @@ export default { if (leftElem || rightElem) { $xetable.checkScrolling() if (isRollY) { - syncBodyScroll(scrollTop, leftElem, rightElem) + syncBodyScroll($xetable, fixedType, scrollTop, leftElem, rightElem) } } } @@ -689,15 +710,15 @@ export default { wheelYInterval = wheelYInterval - (wheelYTotal - wheelYSize) } const { scrollTop, clientHeight, scrollHeight } = bodyElem - const targerTop = scrollTop + (wheelYInterval * (isTopWheel ? -1 : 1)) - bodyElem.scrollTop = targerTop + const targetTop = scrollTop + (wheelYInterval * (isTopWheel ? -1 : 1)) + bodyElem.scrollTop = targetTop if (leftElem) { - leftElem.scrollTop = targerTop + leftElem.scrollTop = targetTop } if (rightElem) { - rightElem.scrollTop = targerTop + rightElem.scrollTop = targetTop } - if (isTopWheel ? targerTop < scrollHeight - clientHeight : targerTop >= 0) { + if (isTopWheel ? targetTop < scrollHeight - clientHeight : targetTop >= 0) { this.wheelTime = setTimeout(handleSmooth, 10) } this.wheelYTotal = wheelYTotal diff --git a/packages/table/src/methods.js b/packages/table/src/methods.js index c53b40efc..3c0359274 100644 --- a/packages/table/src/methods.js +++ b/packages/table/src/methods.js @@ -9,7 +9,7 @@ import { browse, getPaddingTopBottomSize, setScrollTop, setScrollLeft } from '.. import { formats } from '../../v-x-e-table/src/formats' const { getRowid, getRowkey, setCellValue, hasChildrenList, getColumnList } = UtilTools -const { calcHeight, hasClass, addClass, removeClass, getEventTargetNode } = DomTools +const { calcHeight, hasClass, addClass, removeClass, getEventTargetNode, isNodeElement } = DomTools const isWebkit = browse['-webkit'] && !browse.edge const debounceScrollYDuration = browse.msie ? 80 : 20 @@ -294,11 +294,30 @@ const Methods = { }) }, /** - * 手动处理数据 + * 手动处理数据,用于手动排序与筛选 * 对于手动更改了排序、筛选...等条件后需要重新处理数据时可能会用到 */ updateData () { - return this.handleTableData(true).then(this.updateFooter).then(this.recalculate) + const { scrollXLoad, scrollYLoad } = this + return this.handleTableData(true).then(() => { + this.updateFooter() + this.checkSelectionStatus() + if (scrollXLoad || scrollYLoad) { + if (scrollXLoad) { + this.updateScrollXSpace() + } + if (scrollYLoad) { + this.updateScrollYSpace() + } + return this.refreshScroll() + } + }).then(() => { + this.updateCellAreas() + return this.recalculate(true) + }).then(() => { + // 存在滚动行为未结束情况 + setTimeout(() => this.recalculate(), 50) + }) }, handleTableData (force) { const { scrollYLoad, scrollYStore, fullDataRowIdData, afterFullData } = this @@ -1688,15 +1707,22 @@ const Methods = { const leftBodyElem = leftBody ? leftBody.$el : null const rightBodyElem = rightBody ? rightBody.$el : null const tableFooterElem = tableFooter ? tableFooter.$el : null - // 还原滚动条位置 - if (lastScrollLeft || lastScrollTop) { - return restoreScrollLocation(this, lastScrollLeft, lastScrollTop) - } - // 重置 - setScrollTop(tableBodyElem, lastScrollTop) - setScrollTop(leftBodyElem, lastScrollTop) - setScrollTop(rightBodyElem, lastScrollTop) - setScrollLeft(tableFooterElem, lastScrollLeft) + return new Promise(resolve => { + // 还原滚动条位置 + if (lastScrollLeft || lastScrollTop) { + return restoreScrollLocation(this, lastScrollLeft, lastScrollTop).then(() => { + // 存在滚动行为未结束情况 + setTimeout(resolve, 30) + }) + } + // 重置 + setScrollTop(tableBodyElem, lastScrollTop) + setScrollTop(leftBodyElem, lastScrollTop) + setScrollTop(rightBodyElem, lastScrollTop) + setScrollLeft(tableFooterElem, lastScrollLeft) + // 存在滚动行为未结束情况 + setTimeout(resolve, 30) + }) }, /** * 计算单元格列宽,动态分配可用剩余空间 @@ -1965,7 +1991,7 @@ const Methods = { } } else if (layout === 'body') { const emptyBlockElem = elemStore[`${name}-${layout}-emptyBlock`] - if (wrapperElem) { + if (isNodeElement(wrapperElem)) { if (customMaxHeight) { wrapperElem.style.maxHeight = `${fixedType ? customMaxHeight - headerHeight - (showFooter ? 0 : scrollbarHeight) : customMaxHeight - headerHeight}px` } else { @@ -1981,7 +2007,7 @@ const Methods = { if (fixedWrapperElem) { const isRightFixed = fixedType === 'right' const fixedColumn = columnStore[`${fixedType}List`] - if (wrapperElem) { + if (isNodeElement(wrapperElem)) { wrapperElem.style.top = `${headerHeight}px` } fixedWrapperElem.style.height = `${(customHeight > 0 ? customHeight - headerHeight - footerHeight : tableHeight) + headerHeight + footerHeight - scrollbarHeight * (showFooter ? 2 : 1)}px` @@ -2045,7 +2071,7 @@ const Methods = { } tWidth = tableColumn.reduce((previous, column) => previous + column.renderWidth, 0) - if (wrapperElem) { + if (isNodeElement(wrapperElem)) { // 如果是固定列 if (fixedWrapperElem) { wrapperElem.style.top = `${customHeight > 0 ? customHeight - footerHeight : tableHeight + headerHeight}px` diff --git a/packages/tools/src/dom.js b/packages/tools/src/dom.js index 24858f929..0e20e3ee0 100644 --- a/packages/tools/src/dom.js +++ b/packages/tools/src/dom.js @@ -80,6 +80,17 @@ export function setScrollLeft (elem, scrollLeft) { } } +export function setScrollLeftAndTop (elem, scrollLeft, scrollTop) { + if (elem) { + elem.scrollLeft = scrollLeft + elem.scrollTop = scrollTop + } +} + +function isNodeElement (elem) { + return elem && elem.nodeType === 1 +} + export const DomTools = { browse, isPx (val) { @@ -225,7 +236,8 @@ export const DomTools = { } } return num - } + }, + isNodeElement } export default DomTools