-
- 实现树结构深层查找
-
+
树结构筛选
-
-
- 名称
-
-
-
+ :tree-config="{transform: true}"
+ :scroll-y="{gt: 1000}">
+
+
-
+
@@ -31,15 +25,32 @@
diff --git a/package.json b/package.json
index c40a98157..a83c5d363 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "vxe-table",
- "version": "3.4.7",
+ "version": "3.4.7-beta.1",
"description": "一个基于 vue 的 PC 端表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、贼灵活的配置项、扩展接口等...",
"scripts": {
"serve": "vue-cli-service serve",
@@ -66,12 +66,12 @@
"vuex": "^3.4.0",
"xe-ajax": "^4.0.5",
"xe-clipboard": "^1.10.1",
- "xe-utils": "^3.4.0",
+ "xe-utils": "^3.4.2",
"xlsx": "^0.17.0"
},
"peerDependencies": {
"vue": "^2.6.0",
- "xe-utils": "^3.2.0"
+ "xe-utils": "^3.4.2"
},
"vetur": {
"tags": "helper/vetur/tags.json",
diff --git a/packages/edit/src/mixin.js b/packages/edit/src/mixin.js
index 3d5fe2d7e..7a8610e39 100644
--- a/packages/edit/src/mixin.js
+++ b/packages/edit/src/mixin.js
@@ -6,12 +6,12 @@ import { browse } from '../../tools/src/dom'
const { getRowid } = UtilTools
function insertTreeRow (_vm, newRecords, isAppend) {
- const { treeFullData, afterFullData, fullDataRowIdData, fullAllDataRowIdData, treeOpts } = _vm
+ const { tableFullTreeData, afterFullData, fullDataRowIdData, fullAllDataRowIdData, treeOpts } = _vm
const funcName = isAppend ? 'push' : 'unshift'
newRecords.forEach(item => {
const parentRowId = item[treeOpts.parentField]
const rowid = getRowid(_vm, item)
- const matchObj = parentRowId ? XEUtils.findTree(treeFullData, item => parentRowId === item[treeOpts.rowField], treeOpts) : null
+ const matchObj = parentRowId ? XEUtils.findTree(tableFullTreeData, item => parentRowId === item[treeOpts.rowField], treeOpts) : null
if (matchObj) {
const { item: parentRow } = matchObj
const parentRest = fullAllDataRowIdData[getRowid(_vm, parentRow)]
@@ -31,13 +31,12 @@ function insertTreeRow (_vm, newRecords, isAppend) {
}
}
afterFullData[funcName](item)
- treeFullData[funcName](item)
- const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: treeFullData, parent: null, level: 0 }
+ tableFullTreeData[funcName](item)
+ const rest = { row: item, rowid, seq: -1, index: -1, _index: -1, $index: -1, items: tableFullTreeData, parent: null, level: 0 }
fullDataRowIdData[rowid] = rest
fullAllDataRowIdData[rowid] = rest
}
})
- _vm.updateVirtualTreeData()
}
export default {
@@ -59,7 +58,7 @@ export default {
* @param {Row} row 指定行
*/
_insertAt (records, row) {
- const { treeFullData, mergeList, afterFullData, editStore, sYOpts, scrollYLoad, tableFullData, treeConfig, fullDataRowIdData, fullAllDataRowIdData, treeOpts } = this
+ const { tableFullTreeData, mergeList, afterFullData, editStore, tableFullData, treeConfig, fullDataRowIdData, fullAllDataRowIdData, treeOpts } = this
const { transform } = treeOpts
if (!XEUtils.isArray(records)) {
records = [records]
@@ -99,7 +98,7 @@ export default {
} else {
// 如果为虚拟树
if (treeConfig && transform) {
- const matchObj = XEUtils.findTree(treeFullData, item => row[treeOpts.rowField] === item[treeOpts.rowField], treeOpts)
+ const matchObj = XEUtils.findTree(tableFullTreeData, item => row[treeOpts.rowField] === item[treeOpts.rowField], treeOpts)
if (matchObj) {
const { parent: parentRow } = matchObj
const parentChilds = matchObj.items
@@ -122,7 +121,6 @@ export default {
fullDataRowIdData[rowid] = rest
fullAllDataRowIdData[rowid] = rest
})
- this.updateVirtualTreeData()
} else {
if (process.env.VUE_APP_VXE_TABLE_ENV === 'development') {
UtilTools.warn('vxe.error.unableInsert')
@@ -152,13 +150,12 @@ export default {
}
}
editStore.insertList.unshift(...newRecords)
- this.scrollYLoad = !treeConfig && sYOpts.gt > -1 && sYOpts.gt < tableFullData.length
- this.handleTableData(transform)
+ this.handleTableData(treeConfig && treeOpts.transform)
this.updateFooter()
this.cacheRowMap()
this.updateAfterDataIndex()
this.checkSelectionStatus()
- if (scrollYLoad) {
+ if (this.scrollYLoad) {
this.updateScrollYSpace()
}
return this.$nextTick().then(() => {
@@ -178,7 +175,7 @@ export default {
* 如果为空则删除所有
*/
_remove (rows) {
- const { afterFullData, tableFullData, treeFullData, treeConfig, mergeList, editStore, checkboxOpts, selection, isInsertByRow, sYOpts, scrollYLoad, treeOpts } = this
+ const { afterFullData, tableFullData, tableFullTreeData, treeConfig, mergeList, editStore, checkboxOpts, selection, isInsertByRow, treeOpts } = this
const { transform } = treeOpts
const { actived, removeList, insertList } = editStore
const { checkField: property } = checkboxOpts
@@ -214,7 +211,7 @@ export default {
if (treeConfig && transform) {
rows.forEach((row) => {
const rowid = getRowid(this, row)
- const matchObj = XEUtils.findTree(treeFullData, item => rowid === getRowid(this, item), treeOpts)
+ const matchObj = XEUtils.findTree(tableFullTreeData, item => rowid === getRowid(this, item), treeOpts)
if (matchObj) {
const rItems = matchObj.items.splice(matchObj.index, 1)
rest.push(rItems[0])
@@ -223,7 +220,6 @@ export default {
if (afIndex > -1) {
afterFullData.splice(afIndex, 1)
}
- this.updateVirtualTreeData()
})
} else {
rows.forEach(row => {
@@ -259,13 +255,12 @@ export default {
insertList.splice(iIndex, 1)
}
})
- this.scrollYLoad = !treeConfig && sYOpts.gt > -1 && sYOpts.gt < tableFullData.length
- this.handleTableData(transform)
+ this.handleTableData(treeConfig && treeOpts.transform)
this.updateFooter()
this.cacheRowMap()
this.updateAfterDataIndex()
this.checkSelectionStatus()
- if (scrollYLoad) {
+ if (this.scrollYLoad) {
this.updateScrollYSpace()
}
return this.$nextTick().then(() => {
@@ -318,7 +313,7 @@ export default {
* 获取新增的临时数据
*/
_getInsertRecords () {
- const { treeConfig, treeFullData, tableFullData, treeOpts } = this
+ const { treeConfig, tableFullTreeData, tableFullData, treeOpts } = this
const insertList = this.editStore.insertList
const insertRecords = []
if (insertList.length) {
@@ -326,7 +321,7 @@ export default {
if (treeConfig && treeOpts.transform) {
insertList.forEach(row => {
const rowid = getRowid(this, row)
- const matchObj = XEUtils.findTree(treeFullData, item => rowid === getRowid(this, item), treeOpts)
+ const matchObj = XEUtils.findTree(tableFullTreeData, item => rowid === getRowid(this, item), treeOpts)
if (matchObj) {
insertRecords.push(row)
}
diff --git a/packages/filter/src/mixin.js b/packages/filter/src/mixin.js
index 3dc353fe9..6e8a24c25 100644
--- a/packages/filter/src/mixin.js
+++ b/packages/filter/src/mixin.js
@@ -104,7 +104,7 @@ export default {
// 判断面板不能大于表格高度
let maxHeight = null
if (filterHeight >= bodyElem.clientHeight) {
- maxHeight = Math.max(40, bodyElem.clientHeight - (filterFootElem ? filterFootElem.offsetHeight : 0) - (filterHeadElem ? filterHeadElem.offsetHeight : 0))
+ maxHeight = Math.max(60, bodyElem.clientHeight - (filterFootElem ? filterFootElem.offsetHeight : 0) - (filterHeadElem ? filterHeadElem.offsetHeight : 0))
}
if (column.fixed === 'left') {
left = targetElem.offsetLeft + targetElem.offsetParent.offsetLeft - centerWidth
diff --git a/packages/select/src/select.js b/packages/select/src/select.js
index 59a9e512e..a16828a4a 100644
--- a/packages/select/src/select.js
+++ b/packages/select/src/select.js
@@ -13,7 +13,7 @@ function getOptUniqueId () {
}
function getOptkey (_vm) {
- return _vm.optionId || '_XID'
+ return _vm.optionId || '_X_ID'
}
function getOptid (_vm, option) {
diff --git a/packages/table/src/body.js b/packages/table/src/body.js
index ab3f22384..d919985e4 100644
--- a/packages/table/src/body.js
+++ b/packages/table/src/body.js
@@ -377,7 +377,7 @@ function renderRows (h, _vm, $xetable, fixedType, tableData, tableColumn) {
)
}
// 如果是树形表格
- if (treeConfig && !scrollYLoad && treeExpandeds.length) {
+ if (treeConfig && !scrollYLoad && !treeOpts.transform && treeExpandeds.length) {
const rowChildren = row[treeOpts.children]
if (rowChildren && rowChildren.length && treeExpandeds.indexOf(row) > -1) {
rows.push(...renderRows(h, _vm, $xetable, fixedType, rowChildren, tableColumn))
diff --git a/packages/table/src/methods.js b/packages/table/src/methods.js
index 798efd8b5..bcee9b73f 100644
--- a/packages/table/src/methods.js
+++ b/packages/table/src/methods.js
@@ -301,9 +301,33 @@ const Methods = {
return this.handleTableData(true).then(this.updateFooter).then(this.recalculate)
},
handleTableData (force) {
- const { scrollYLoad, scrollYStore } = this
- const fullData = force ? this.updateAfterFullData() : this.afterFullData
- this.tableData = scrollYLoad ? fullData.slice(scrollYStore.startIndex, scrollYStore.endIndex) : fullData.slice(0)
+ const { treeConfig, scrollYLoad, scrollYStore, fullDataRowIdData, treeExpandeds, treeOpts } = this
+ let fullList = []
+ // 是否进行数据处理
+ if (force) {
+ this.updateAfterFullData()
+ }
+ // 如果为虚拟树,将树结构拍平
+ if (treeConfig && treeOpts.transform) {
+ const expandMaps = new Map()
+ XEUtils.eachTree(this.afterTreeFullData, (row, index, items, path, parent) => {
+ if (!parent || (expandMaps.has(parent) && treeExpandeds.indexOf(parent) > -1)) {
+ expandMaps.set(row, 1)
+ fullList.push(row)
+ }
+ }, { children: treeOpts.mapChildren })
+ } else {
+ fullList = this.afterFullData
+ }
+ const tableData = scrollYLoad ? fullList.slice(scrollYStore.startIndex, scrollYStore.endIndex) : fullList.slice(0)
+ tableData.forEach((row, $index) => {
+ const rowid = getRowid(this, row)
+ const rest = fullDataRowIdData[rowid]
+ if (rest) {
+ rest.$index = $index
+ }
+ })
+ this.tableData = tableData
return this.$nextTick()
},
updateScrollYStatus (fullData) {
@@ -334,13 +358,24 @@ const Methods = {
if (!treeOpts.children) {
UtilTools.error('vxe.error.reqProp', ['tree-config.children'])
}
+ if (!treeOpts.mapChildren) {
+ UtilTools.error('vxe.error.reqProp', ['tree-config.mapChildren'])
+ }
+ if (treeOpts.children === treeOpts.mapChildren) {
+ UtilTools.error('vxe.error.errConflicts', ['tree-config.children', 'tree-config.mapChildren'])
+ }
fullData.forEach(row => {
if (row[treeOpts.children] && row[treeOpts.children].length) {
UtilTools.warn('vxe.error.errConflicts', ['tree-config.transform', `row.${treeOpts.children}`])
}
})
}
- treeData = XEUtils.toArrayTree(fullData, { key: treeOpts.rowField, parentKey: treeOpts.parentField, children: treeOpts.children })
+ treeData = XEUtils.toArrayTree(fullData, {
+ key: treeOpts.rowField,
+ parentKey: treeOpts.parentField,
+ children: treeOpts.children,
+ mapChildren: treeOpts.mapChildren
+ })
fullData = treeData.slice(0)
} else {
treeData = fullData.slice(0)
@@ -356,7 +391,7 @@ const Methods = {
this.scrollYLoad = sYLoad
// 全量数据
this.tableFullData = fullData
- this.treeFullData = treeData
+ this.tableFullTreeData = treeData
// 缓存数据
this.cacheRowMap(true)
// 原始数据
@@ -530,7 +565,7 @@ const Methods = {
* 牺牲数据组装的耗时,用来换取使用过程中的流畅
*/
cacheRowMap (source) {
- const { treeConfig, treeOpts, tableFullData, fullDataRowMap, fullAllDataRowMap } = this
+ const { treeConfig, treeOpts, tableFullData, fullDataRowMap, fullAllDataRowMap, tableFullTreeData } = this
let { fullDataRowIdData, fullAllDataRowIdData } = this
const rowkey = getRowkey(this)
const isLazy = treeConfig && treeOpts.lazy
@@ -560,7 +595,7 @@ const Methods = {
fullAllDataRowIdData = this.fullAllDataRowIdData = {}
fullAllDataRowMap.clear()
if (treeConfig) {
- XEUtils.eachTree(tableFullData, handleCache, treeOpts)
+ XEUtils.eachTree(tableFullTreeData, handleCache, treeOpts)
} else {
tableFullData.forEach(handleCache)
}
@@ -1078,10 +1113,12 @@ const Methods = {
* 如果存在筛选条件,继续处理
*/
updateAfterFullData () {
- const { tableFullColumn, tableFullData, filterOpts, sortOpts } = this
+ const { tableFullColumn, tableFullData, filterOpts, sortOpts, treeConfig, treeOpts, tableFullTreeData } = this
const { remote: allRemoteFilter, filterMethod: allFilterMethod } = filterOpts
const { remote: allRemoteSort, sortMethod: allSortMethod, multiple: sortMultiple } = sortOpts
- let tableData = tableFullData.slice(0)
+ const { transform } = treeOpts
+ let tableData = []
+ let tableTree = []
const filterColumns = []
const orderColumns = []
tableFullColumn.forEach(column => {
@@ -1104,7 +1141,7 @@ const Methods = {
}
})
if (filterColumns.length) {
- tableData = tableData.filter(row => {
+ const handleFilter = (row) => {
return filterColumns.every(({ column, valueList, itemList }) => {
if (valueList.length && !allRemoteFilter) {
const { filterMethod, filterRender } = column
@@ -1125,7 +1162,16 @@ const Methods = {
}
return true
})
- })
+ }
+ if (treeConfig && transform) {
+ tableTree = XEUtils.searchTree(tableFullTreeData, handleFilter, { ...treeOpts, original: true })
+ } else {
+ tableData = treeConfig ? tableFullTreeData.filter(handleFilter) : tableFullData.filter(handleFilter)
+ tableTree = tableData
+ }
+ } else {
+ tableData = treeConfig ? tableFullTreeData.slice(0) : tableFullData.slice(0)
+ tableTree = tableData
}
const firstOrderColumn = orderColumns[0]
if (!allRemoteSort && firstOrderColumn) {
@@ -1145,18 +1191,20 @@ const Methods = {
tableData = XEUtils.orderBy(tableData, sortByConfs || [firstOrderColumn].map(({ column, order }) => [getOrderField(this, column), order]))
}
}
+ tableTree = tableData
}
this.afterFullData = tableData
- return tableData
+ this.afterTreeFullData = tableTree
+ this.updateAfterDataIndex()
},
/**
* 预编译
* 对渲染中的数据提前解析序号及索引。牺牲提前编译耗时换取渲染中额外损耗,使运行时更加流畅
*/
updateAfterDataIndex () {
- const { treeConfig, afterFullData, fullDataRowIdData, fullAllDataRowIdData, treeFullData, treeOpts } = this
+ const { treeConfig, afterFullData, fullDataRowIdData, fullAllDataRowIdData, afterTreeFullData, treeOpts } = this
if (treeConfig) {
- XEUtils.eachTree(treeFullData, (row, index, items, path) => {
+ XEUtils.eachTree(afterTreeFullData, (row, index, items, path) => {
const rowid = getRowid(this, row)
const allrest = fullAllDataRowIdData[rowid]
const fullrest = fullDataRowIdData[rowid]
@@ -3754,7 +3802,7 @@ const Methods = {
return this.handleAsyncTreeExpandChilds(row)
}).then(() => {
if (transform) {
- return this.updateVirtualTreeData()
+ return this.handleTableData()
}
}).then(() => {
return this.recalculate()
@@ -3900,23 +3948,6 @@ const Methods = {
}
return Promise.all(result).then(this.recalculate)
},
- updateVirtualTreeData () {
- const { scrollYLoad: oldScrollYLoad, treeExpandeds, treeOpts, treeFullData } = this
- const fullData = []
- const expandMaps = new Map()
- XEUtils.eachTree(treeFullData, (row, index, items, path, parent) => {
- if (!parent || (expandMaps.has(parent) && treeExpandeds.indexOf(parent) > -1)) {
- expandMaps.set(row, 1)
- fullData.push(row)
- }
- }, treeOpts)
- const scrollYLoad = this.updateScrollYStatus(fullData)
- this.tableFullData = scrollYLoad ? fullData : treeFullData
- if (scrollYLoad || oldScrollYLoad !== scrollYLoad) {
- return this.handleTableData(true).then(() => this.recalculate())
- }
- return this.$nextTick()
- },
/**
* 虚拟树的展开与收起
* @param rows
@@ -3925,7 +3956,7 @@ const Methods = {
*/
handleVirtualTreeExpand (rows, expanded) {
return this.handleBaseTreeExpand(rows, expanded).then(() => {
- return this.updateVirtualTreeData()
+ return this.handleTableData()
}).then(() => {
return this.recalculate()
})
@@ -3973,7 +4004,7 @@ const Methods = {
if (reserve) {
XEUtils.eachTree(tableFullData, row => this.handleTreeExpandReserve(row, false), treeOpts)
}
- return this.updateVirtualTreeData().then(() => {
+ return this.handleTableData().then(() => {
if (isExists) {
this.recalculate()
}
diff --git a/packages/tools/src/utils.js b/packages/tools/src/utils.js
index 3e8e964bd..ff8bcb41e 100644
--- a/packages/tools/src/utils.js
+++ b/packages/tools/src/utils.js
@@ -183,7 +183,7 @@ export const UtilTools = {
},
// 行主键 key
getRowkey ($xetable) {
- return $xetable.rowId || '_XID'
+ return $xetable.rowId || '_X_ID'
},
// 行主键 value
getRowid ($xetable, row) {
diff --git a/packages/v-x-e-table/src/conf.js b/packages/v-x-e-table/src/conf.js
index ba986c4b4..255c3e29e 100644
--- a/packages/v-x-e-table/src/conf.js
+++ b/packages/v-x-e-table/src/conf.js
@@ -49,7 +49,7 @@ export default {
// storage: false,
// checkMethod () {}
// },
- // rowId: '_XID', // 行数据的唯一主键字段名
+ // rowId: '_X_ID', // 行数据的唯一主键字段名
sortConfig: {
// remote: false,
// trigger: 'default',
@@ -67,6 +67,7 @@ export default {
parentField: 'parentId',
children: 'children',
hasChild: 'hasChild',
+ mapChildren: '_X_CHILD',
indent: 20,
showIcon: true
},