1 Star 1 Fork 3

XE / vxe-table-plugin-virtual-tree

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
index.ts 27.90 KB
一键复制 编辑 原始数据 按行查看 历史
xuliangzhan 提交于 2021-10-31 20:42 . 即将停止维护
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
/* eslint-disable no-unused-vars */
import Vue, { CreateElement, VNodeChildren, VNode } from 'vue'
import XEUtils from 'xe-utils'
import {
VXETable,
Table,
Grid,
RowInfo,
ColumnOptions,
ColumnCellRenderParams
} from 'vxe-table'
/* eslint-enable no-unused-vars */
function hasChilds (_vm: VirtualTree, row: RowInfo) {
const childList = row[_vm.treeOpts.children]
return childList && childList.length
}
function renderDefaultForm (h: CreateElement, _vm: VirtualTree) {
const { proxyConfig, proxyOpts, formData, formConfig, formOpts } = _vm
if (formConfig && formOpts.items && formOpts.items.length) {
if (!formOpts.inited) {
formOpts.inited = true
const beforeItem = proxyOpts.beforeItem
if (proxyOpts && beforeItem) {
formOpts.items.forEach((item: any) => {
beforeItem.call(_vm, { $grid: _vm, item })
})
}
}
return [
h('vxe-form', {
props: Object.assign({}, formOpts, {
data: proxyConfig && proxyOpts.form ? formData : formOpts.data
}),
on: {
submit: _vm.submitEvent,
reset: _vm.resetEvent,
'submit-invalid': _vm.submitInvalidEvent,
'toggle-collapse': _vm.togglCollapseEvent
},
ref: 'form'
})
]
}
return []
}
function getToolbarSlots (_vm: VirtualTree) {
const { $scopedSlots, toolbarOpts } = _vm
const toolbarOptSlots = toolbarOpts.slots
let $buttons
let $tools
const slots: { [key: string]: any } = {}
if (toolbarOptSlots) {
$buttons = toolbarOptSlots.buttons
$tools = toolbarOptSlots.tools
if ($buttons && $scopedSlots[$buttons]) {
$buttons = $scopedSlots[$buttons]
}
if ($tools && $scopedSlots[$tools]) {
$tools = $scopedSlots[$tools]
}
}
if ($buttons) {
slots.buttons = $buttons
}
if ($tools) {
slots.tools = $tools
}
return slots
}
function getPagerSlots (_vm: VirtualTree) {
const { $scopedSlots, pagerOpts } = _vm
const pagerOptSlots = pagerOpts.slots
const slots: { [key: string]: any } = {}
let $left
let $right
if (pagerOptSlots) {
$left = pagerOptSlots.left
$right = pagerOptSlots.right
if ($left && $scopedSlots[$left]) {
$left = $scopedSlots[$left]
}
if ($right && $scopedSlots[$right]) {
$right = $scopedSlots[$right]
}
}
if ($left) {
slots.left = $left
}
if ($right) {
slots.right = $right
}
return slots
}
function getTableOns (_vm: VirtualTree) {
const { $listeners, proxyConfig, proxyOpts } = _vm
const ons: { [key: string]: Function } = {}
XEUtils.each($listeners, (cb, type) => {
ons[type] = (...args: any[]) => {
_vm.$emit(type, ...args)
}
})
ons['checkbox-all'] = _vm.checkboxAllEvent
ons['checkbox-change'] = _vm.checkboxChangeEvent
if (proxyConfig) {
if (proxyOpts.sort) {
ons['sort-change'] = _vm.sortChangeEvent
}
if (proxyOpts.filter) {
ons['filter-change'] = _vm.filterChangeEvent
}
}
return ons
}
function errorLog (log: string, args?: any) {
console.error(args ? XEUtils.template(log, args) : log)
}
declare module 'vxe-table/lib/vxe-table' {
interface VXETableStatic {
Vue: typeof Vue;
Grid: Grid;
Table: Table;
}
}
interface VirtualTree extends Grid {
$refs: {
xTable: Table;
[key: string]: any;
};
_loadTreeData(data: RowInfo[]): Promise<any>;
handleColumns(columns: ColumnOptions[]): ColumnOptions[];
toVirtualTree(treeData: RowInfo[]): RowInfo[];
handleExpanding(row: RowInfo): RowInfo[];
handleCollapsing(row: RowInfo): RowInfo[];
[key: string]: any;
}
interface VirtualTreeOptions {
data?: (this: VirtualTree) => any;
computed?: { [key: string]: (this: VirtualTree) => any }
watch?: { [key: string]: (this: VirtualTree, ...args: any[]) => any }
created?: (this: VirtualTree) => any;
render?: (this: VirtualTree, h: CreateElement) => VNode;
methods?: { [key: string]: (this: VirtualTree, ...args: any[]) => any }
[key: string]: any;
}
function registerComponent (vxetable: typeof VXETable) {
const { setup, t } = vxetable
const GlobalConfig = setup()
const propKeys = Object.keys(vxetable.Table.props).filter(name => ['data', 'treeConfig'].indexOf(name) === -1)
const options: VirtualTreeOptions = {
name: 'VxeVirtualTree',
extends: vxetable.Grid,
data () {
return {
removeList: [],
treeLazyLoadeds: []
}
},
computed: {
treeOpts () {
return Object.assign({}, GlobalConfig.table.treeConfig, this.treeConfig)
},
checkboxOpts () {
return Object.assign({}, GlobalConfig.table.checkboxConfig, this.checkboxConfig)
},
tableExtendProps () {
let rest: { [key: string]: any } = {}
propKeys.forEach(key => {
rest[key] = this[key]
})
if (rest.checkboxConfig) {
rest.checkboxConfig = this.checkboxOpts
}
return rest
}
},
watch: {
columns (value: ColumnOptions[]) {
this.handleColumns(value)
},
data (value: any[]) {
this.loadData(value)
}
},
created () {
const { $vxe, treeOpts, data, columns } = this
Object.assign(this, {
fullTreeData: [],
treeTableData: [],
fullTreeRowMap: new Map()
})
if (this.keepSource) {
errorLog($vxe.t('vxe.error.notProp'), ['keep-source'])
}
if (treeOpts.line) {
errorLog($vxe.t('vxe.error.notProp'), ['checkbox-config.line'])
}
if (columns) {
this.handleColumns(columns)
}
if (data) {
this.reloadData(data)
}
},
render (h: CreateElement) {
const { vSize, isZMax } = this
const $scopedSlots: any = this.$scopedSlots
const hasForm = !!($scopedSlots.form || this.formConfig)
const hasToolbar = !!($scopedSlots.toolbar || this.toolbarConfig || this.toolbar)
const hasPager = !!($scopedSlots.pager || this.pagerConfig)
return h('div', {
class: ['vxe-grid', 'vxe-virtual-tree', {
[`size--${vSize}`]: vSize,
't--animat': !!this.animat,
'is--round': this.round,
'is--maximize': isZMax,
'is--loading': this.loading || this.tableLoading
}],
style: this.renderStyle
}, [
/**
* 渲染表单
*/
hasForm ? h('div', {
ref: 'formWrapper',
staticClass: 'vxe-grid--form-wrapper'
}, $scopedSlots.form
? $scopedSlots.form.call(this, { $grid: this }, h)
: renderDefaultForm(h, this)
) : null,
/**
* 渲染工具栏
*/
hasToolbar ? h('div', {
ref: 'toolbarWrapper',
class: 'vxe-grid--toolbar-wrapper'
}, $scopedSlots.toolbar
? $scopedSlots.toolbar.call(this, { $grid: this }, h)
: [
h('vxe-toolbar', {
props: this.toolbarOpts,
ref: 'xToolbar',
scopedSlots: getToolbarSlots(this)
})
]
) : null,
/**
* 渲染表格顶部区域
*/
$scopedSlots.top ? h('div', {
ref: 'topWrapper',
staticClass: 'vxe-grid--top-wrapper'
}, $scopedSlots.top.call(this, { $grid: this }, h)) : null,
/**
* 渲染表格
*/
h('vxe-table', {
props: this.tableProps,
on: getTableOns(this),
scopedSlots: $scopedSlots,
ref: 'xTable'
}, this.$slots.default),
/**
* 渲染表格底部区域
*/
$scopedSlots.bottom ? h('div', {
ref: 'bottomWrapper',
staticClass: 'vxe-grid--bottom-wrapper'
}, $scopedSlots.bottom.call(this, { $grid: this }, h)) : null,
/**
* 渲染分页
*/
hasPager ? h('div', {
ref: 'pagerWrapper',
staticClass: 'vxe-grid--pager-wrapper'
}, $scopedSlots.pager
? $scopedSlots.pager.call(this, { $grid: this }, h)
: [
h('vxe-pager', {
props: this.pagerProps,
on: {
'page-change': this.pageChangeEvent
},
scopedSlots: getPagerSlots(this)
})
]
) : null
])
},
methods: {
loadColumn (columns: ColumnOptions[]) {
return this.$nextTick().then(() => {
const { $vxe, $scopedSlots, renderTreeIcon, treeOpts } = this
XEUtils.eachTree(columns, column => {
if (column.treeNode) {
if (!column.slots) {
column.slots = {}
}
column.slots.icon = renderTreeIcon
}
if (column.slots) {
XEUtils.each(column.slots, (func, name, slots) => {
if (!XEUtils.isFunction(func)) {
if ($scopedSlots[func]) {
slots[name] = $scopedSlots[func]
} else {
slots[name] = null
errorLog($vxe.t('vxe.error.notSlot'), [func])
}
}
})
}
}, treeOpts)
this.$refs.xTable.loadColumn(columns)
})
},
renderTreeIcon (params: ColumnCellRenderParams, h: CreateElement, cellVNodes: VNodeChildren) {
const { treeLazyLoadeds, treeOpts } = this
let { isHidden, row } = params
const { children, hasChild, indent, lazy, trigger, iconLoaded, showIcon, iconOpen, iconClose } = treeOpts
let rowChilds = row[children]
let hasLazyChilds = false
let isAceived = false
let isLazyLoaded = false
let on: { [key: string]: Function } = {}
if (!isHidden) {
isAceived = row._X_EXPAND
if (lazy) {
isLazyLoaded = treeLazyLoadeds.indexOf(row) > -1
hasLazyChilds = row[hasChild]
}
}
if (!trigger || trigger === 'default') {
on.click = (evnt: Event) => this.triggerTreeExpandEvent(evnt, params)
}
return [
h('div', {
class: ['vxe-cell--tree-node', {
'is--active': isAceived
}],
style: {
paddingLeft: `${row._X_LEVEL * indent}px`
}
}, [
showIcon && ((rowChilds && rowChilds.length) || hasLazyChilds) ? [
h('div', {
class: 'vxe-tree--btn-wrapper',
on
}, [
h('i', {
class: ['vxe-tree--node-btn', isLazyLoaded ? (iconLoaded || GlobalConfig.icon.TABLE_TREE_LOADED) : (isAceived ? (iconOpen || GlobalConfig.icon.TABLE_TREE_OPEN) : (iconClose || GlobalConfig.icon.TABLE_TREE_CLOSE))]
})
])
] : null,
h('div', {
class: 'vxe-tree-cell'
}, cellVNodes)
])
]
},
_loadTreeData (data: RowInfo[]) {
const selectRow = this.getRadioRecord()
return this.$nextTick()
.then(() => this.$refs.xTable.loadData(data))
.then(() => {
if (selectRow) {
this.setRadioRow(selectRow)
}
})
},
loadData (data: any[]) {
return this._loadTreeData(this.toVirtualTree(data))
},
reloadData (data: any[]) {
return this.$nextTick()
.then(() => this.$refs.xTable.reloadData(this.toVirtualTree(data)))
.then(() => this.handleDefaultTreeExpand())
},
isTreeExpandByRow (row: RowInfo) {
return !!row._X_EXPAND
},
setTreeExpansion (rows: RowInfo | RowInfo[], expanded: boolean) {
return this.setTreeExpand(rows, expanded)
},
handleAsyncTreeExpandChilds (row: RowInfo) {
const { treeLazyLoadeds, treeOpts, checkboxOpts } = this
const { loadMethod, children } = treeOpts
const { checkStrictly } = checkboxOpts
return new Promise(resolve => {
if (loadMethod) {
treeLazyLoadeds.push(row)
loadMethod({ row }).catch(() => []).then((childs: any[]) => {
row._X_LOADED = true
XEUtils.remove(treeLazyLoadeds, item => item === row)
if (!XEUtils.isArray(childs)) {
childs = []
}
if (childs) {
row[children] = childs.map(item => {
item._X_LOADED = false
item._X_EXPAND = false
item._X_INSERT = false
item._X_LEVEL = row._X_LEVEL + 1
return item
})
if (childs.length && !row._X_EXPAND) {
this.virtualExpand(row, true)
}
// 如果当前节点已选中,则展开后子节点也被选中
if (!checkStrictly && this.isCheckedByCheckboxRow(row)) {
this.setCheckboxRow(childs, true)
}
}
resolve(this.$nextTick().then(() => this.recalculate()))
})
} else {
resolve()
}
})
},
setTreeExpand (rows: any, expanded: boolean) {
const { treeLazyLoadeds, treeOpts, tableFullData, treeNodeColumn } = this
const { lazy, hasChild, accordion, toggleMethod } = treeOpts
const result: any[] = []
if (rows) {
if (!XEUtils.isArray(rows)) {
rows = [rows]
}
const columnIndex = this.getColumnIndex(treeNodeColumn)
const $columnIndex = this.getVMColumnIndex(treeNodeColumn)
let validRows = toggleMethod ? rows.filter((row: RowInfo) => toggleMethod({ expanded, column: treeNodeColumn, row, columnIndex, $columnIndex })) : rows
if (accordion) {
validRows = validRows.length ? [validRows[validRows.length - 1]] : []
// 同一级只能展开一个
const matchObj = XEUtils.findTree(tableFullData, item => item === rows[0], treeOpts)
if (matchObj) {
matchObj.items.forEach(row => {
row._X_EXPAND = false
})
}
}
validRows.forEach((row: any) => {
const isLoad = lazy && row[hasChild] && !row._X_LOADED && treeLazyLoadeds.indexOf(row) === -1
// 是否使用懒加载
if (expanded && isLoad) {
result.push(this.handleAsyncTreeExpandChilds(row))
} else {
if (hasChilds(this, row)) {
this.virtualExpand(row, !!expanded)
}
}
})
return Promise.all(result).then(() => {
this._loadTreeData(this.treeTableData)
return this.recalculate()
})
}
return this.$nextTick()
},
setAllTreeExpansion (expanded: boolean) {
return this.setAllTreeExpand(expanded)
},
setAllTreeExpand (expanded: boolean) {
return this._loadTreeData(this.virtualAllExpand(expanded))
},
toggleTreeExpansion (row: RowInfo) {
return this.toggleTreeExpand(row)
},
triggerTreeExpandEvent (evnt: Event, params: ColumnCellRenderParams) {
const { treeOpts, treeLazyLoadeds } = this
const { row, column } = params
const { lazy } = treeOpts
if (!lazy || treeLazyLoadeds.indexOf(row) === -1) {
const expanded = !this.isTreeExpandByRow(row)
this.setTreeExpand(row, expanded)
this.$emit('toggle-tree-expand', { expanded, column, row, $event: evnt })
}
},
toggleTreeExpand (row: RowInfo) {
return this._loadTreeData(this.virtualExpand(row, !row._X_EXPAND))
},
getTreeExpandRecords () {
const { fullTreeData, treeOpts } = this
const treeExpandRecords: RowInfo[] = []
XEUtils.eachTree(fullTreeData, row => {
if (row._X_EXPAND && hasChilds(this, row)) {
treeExpandRecords.push(row)
}
}, treeOpts)
return treeExpandRecords
},
clearTreeExpand () {
return this.setAllTreeExpand(false)
},
handleColumns (columns: ColumnOptions[]) {
const { $vxe, renderTreeIcon, checkboxOpts } = this
if (columns) {
if ((!checkboxOpts.checkField || !checkboxOpts.halfField) && columns.some(conf => conf.type === 'checkbox')) {
errorLog($vxe.t('vxe.error.reqProp'), ['table.checkbox-config.checkField | table.checkbox-config.halfField'])
return []
}
const treeNodeColumn = columns.find(conf => conf.treeNode)
if (treeNodeColumn) {
let slots = treeNodeColumn.slots || {}
slots.icon = renderTreeIcon
treeNodeColumn.slots = slots
this.treeNodeColumn = treeNodeColumn
}
return columns
}
return []
},
/**
* 获取表格数据集,包含新增、删除
* 不支持修改
*/
getRecordset () {
return {
insertRecords: this.getInsertRecords(),
removeRecords: this.getRemoveRecords(),
updateRecords: []
}
},
isInsertByRow (row: RowInfo) {
return !!row._X_INSERT
},
getInsertRecords () {
const { treeOpts } = this
const insertRecords: RowInfo[] = []
XEUtils.eachTree(this.fullTreeData, row => {
if (row._X_INSERT) {
insertRecords.push(row)
}
}, treeOpts)
return insertRecords
},
insert (records: RowInfo | RowInfo[]) {
return this.insertAt(records, null)
},
/**
* 支持任意层级插入与删除
*/
insertAt (records: any, row: number | RowInfo | null) {
const { fullTreeData, treeTableData, treeOpts } = this
if (!XEUtils.isArray(records)) {
records = [records]
}
let newRecords = records.map((record: any) => this.defineField(Object.assign({
_X_LOADED: false,
_X_EXPAND: false,
_X_INSERT: true,
_X_LEVEL: 0
}, record)))
if (!row) {
fullTreeData.unshift(...newRecords)
treeTableData.unshift(...newRecords)
} else {
if (row === -1) {
fullTreeData.push(...newRecords)
treeTableData.push(...newRecords)
} else {
let matchObj = XEUtils.findTree(fullTreeData, item => item === row, treeOpts)
if (!matchObj || matchObj.index === -1) {
throw new Error(t('vxe.error.unableInsert'))
}
let { items, index, nodes } = matchObj
let rowIndex = treeTableData.indexOf(row)
if (rowIndex > -1) {
treeTableData.splice(rowIndex, 0, ...newRecords)
}
items.splice(index, 0, ...newRecords)
newRecords.forEach((item: any) => {
item._X_LEVEL = nodes.length - 1
})
}
}
return this._loadTreeData(treeTableData).then(() => {
return {
row: newRecords.length ? newRecords[newRecords.length - 1] : null,
rows: newRecords
}
})
},
/**
* 获取已删除的数据
*/
getRemoveRecords () {
return this.removeList
},
removeSelecteds () {
return this.removeCheckboxRow()
},
/**
* 删除选中数据
*/
removeCheckboxRow () {
return this.remove(this.getCheckboxRecords()).then((params: any) => {
this.clearSelection()
return params
})
},
remove (rows: any) {
const { removeList, fullTreeData, treeOpts } = this
let rest: RowInfo[] = []
if (!rows) {
rows = fullTreeData
} else if (!XEUtils.isArray(rows)) {
rows = [rows]
}
rows.forEach((row: any) => {
let matchObj = XEUtils.findTree(fullTreeData, item => item === row, treeOpts)
if (matchObj) {
const { item, items, index, parent }: any = matchObj
if (!this.isInsertByRow(row)) {
removeList.push(row)
}
if (parent) {
let isExpand = this.isTreeExpandByRow(parent)
if (isExpand) {
this.handleCollapsing(parent)
}
items.splice(index, 1)
if (isExpand) {
this.handleExpanding(parent)
}
} else {
this.handleCollapsing(item)
items.splice(index, 1)
this.treeTableData.splice(this.treeTableData.indexOf(item), 1)
}
rest.push(item)
}
})
return this._loadTreeData(this.treeTableData).then(() => {
return { row: rest.length ? rest[rest.length - 1] : null, rows: rest }
})
},
/**
* 处理默认展开树节点
*/
handleDefaultTreeExpand () {
let { treeConfig, treeOpts, tableFullData } = this
if (treeConfig) {
let { children, expandAll, expandRowKeys } = treeOpts
if (expandAll) {
this.setAllTreeExpand(true)
} else if (expandRowKeys && this.rowId) {
let rowkey = this.rowId
expandRowKeys.forEach((rowid: any) => {
let matchObj = XEUtils.findTree(tableFullData, item => rowid === XEUtils.get(item, rowkey), treeOpts)
let rowChildren = matchObj ? matchObj.item[children] : 0
if (rowChildren && rowChildren.length) {
this.setTreeExpand(matchObj.item, true)
}
})
}
}
},
/**
* 定义树属性
*/
toVirtualTree (treeData: RowInfo[]) {
const { treeOpts } = this
let fullTreeRowMap = this.fullTreeRowMap
fullTreeRowMap.clear()
XEUtils.eachTree(treeData, (item, index, items, paths, parent, nodes) => {
item._X_LOADED = false
item._X_EXPAND = false
item._X_INSERT = false
item._X_LEVEL = nodes.length - 1
fullTreeRowMap.set(item, { item, index, items, paths, parent, nodes })
}, treeOpts)
this.fullTreeData = treeData.slice(0)
this.treeTableData = treeData.slice(0)
return treeData
},
/**
* 展开/收起树节点
*/
virtualExpand (row: RowInfo, expanded: boolean) {
const { treeOpts, treeNodeColumn } = this
const { toggleMethod } = treeOpts
const columnIndex = this.getColumnIndex(treeNodeColumn)
const $columnIndex = this.getVMColumnIndex(treeNodeColumn)
if (!toggleMethod || toggleMethod({ expanded, row, column: treeNodeColumn, columnIndex, $columnIndex })) {
if (row._X_EXPAND !== expanded) {
if (row._X_EXPAND) {
this.handleCollapsing(row)
} else {
this.handleExpanding(row)
}
}
}
return this.treeTableData
},
// 展开节点
handleExpanding (row: RowInfo) {
if (hasChilds(this, row)) {
const { treeTableData, treeOpts } = this
let childRows = row[treeOpts.children]
let expandList: RowInfo[] = []
let rowIndex = treeTableData.indexOf(row)
if (rowIndex === -1) {
throw new Error('Expanding error')
}
const expandMaps: Map<RowInfo, Number> = new Map()
XEUtils.eachTree(childRows, (item, index, obj, paths, parent, nodes) => {
if (!parent || (parent._X_EXPAND && expandMaps.has(parent))) {
expandMaps.set(item, 1)
expandList.push(item)
}
}, treeOpts)
row._X_EXPAND = true
treeTableData.splice(rowIndex + 1, 0, ...expandList)
}
return this.treeTableData
},
// 收起节点
handleCollapsing (row: RowInfo) {
if (hasChilds(this, row)) {
const { treeTableData, treeOpts } = this
let childRows = row[treeOpts.children]
let nodeChildList: RowInfo[] = []
XEUtils.eachTree(childRows, item => {
nodeChildList.push(item)
}, treeOpts)
row._X_EXPAND = false
this.treeTableData = treeTableData.filter((item: any) => nodeChildList.indexOf(item) === -1)
}
return this.treeTableData
},
/**
* 展开/收起所有树节点
*/
virtualAllExpand (expanded: boolean) {
const { treeOpts } = this
if (expanded) {
const tableList: RowInfo[] = []
XEUtils.eachTree(this.fullTreeData, row => {
row._X_EXPAND = expanded
tableList.push(row)
}, treeOpts)
this.treeTableData = tableList
} else {
XEUtils.eachTree(this.fullTreeData, row => {
row._X_EXPAND = expanded
}, treeOpts)
this.treeTableData = this.fullTreeData.slice(0)
}
return this.treeTableData
},
checkboxAllEvent (params: any) {
const { checkboxOpts, treeOpts } = this
const { checkField, halfField, checkStrictly } = checkboxOpts
const { checked } = params
if (checkField && !checkStrictly) {
XEUtils.eachTree(this.fullTreeData, row => {
row[checkField] = checked
if (halfField) {
row[halfField] = false
}
}, treeOpts)
}
this.$emit('checkbox-all', params)
},
checkboxChangeEvent (params: any) {
const { checkboxOpts, treeOpts } = this
const { checkField, halfField, checkStrictly } = checkboxOpts
const { row, checked } = params
if (checkField && !checkStrictly) {
XEUtils.eachTree([row], row => {
row[checkField] = checked
if (halfField) {
row[halfField] = false
}
}, treeOpts)
this.checkParentNodeSelection(row)
}
this.$emit('checkbox-change', params)
},
checkParentNodeSelection (row: RowInfo) {
const { checkboxOpts, treeOpts } = this
const { children } = treeOpts
const { checkField, halfField, checkStrictly } = checkboxOpts
const matchObj = XEUtils.findTree(this.fullTreeData, item => item === row, treeOpts)
if (matchObj && checkField && !checkStrictly) {
const parentRow: RowInfo = matchObj.parent
if (parentRow) {
const isAll = parentRow[children].every((item: RowInfo) => item[checkField])
if (halfField && !isAll) {
parentRow[halfField] = parentRow[children].some((item: RowInfo) => item[checkField] || item[halfField])
}
parentRow[checkField] = isAll
this.checkParentNodeSelection(parentRow)
} else {
this.$refs.xTable.checkSelectionStatus()
}
}
},
getCheckboxRecords () {
const { checkboxOpts, treeOpts } = this
const { checkField } = checkboxOpts
if (checkField) {
const records: RowInfo[] = []
XEUtils.eachTree(this.fullTreeData, row => {
if (row[checkField]) {
records.push(row)
}
}, treeOpts)
return records
}
return this.$refs.xTable.getCheckboxRecords()
},
getCheckboxIndeterminateRecords () {
const { checkboxOpts, treeOpts } = this
const { halfField } = checkboxOpts
if (halfField) {
const records: RowInfo[] = []
XEUtils.eachTree(this.fullTreeData, row => {
if (row[halfField]) {
records.push(row)
}
}, treeOpts)
return records
}
return this.$refs.xTable.getCheckboxIndeterminateRecords()
}
}
}
vxetable.Vue.component(options.name, options)
}
/**
* 基于 vxe-table 表格的增强插件,实现简单的虚拟树表格
*/
export const VXETablePluginVirtualTree = {
install (vxetable: typeof VXETable) {
registerComponent(vxetable)
}
}
if (typeof window !== 'undefined' && window.VXETable && window.VXETable.use) {
window.VXETable.use(VXETablePluginVirtualTree)
}
export default VXETablePluginVirtualTree
TypeScript
1
https://gitee.com/x-extends/vxe-table-plugin-virtual-tree.git
git@gitee.com:x-extends/vxe-table-plugin-virtual-tree.git
x-extends
vxe-table-plugin-virtual-tree
vxe-table-plugin-virtual-tree
master

搜索帮助