1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249 |
- import XEUtils from 'xe-utils/ctor'
- import GlobalConfig from '../../conf'
- import VXETable from '../../v-x-e-table'
- import VxeTableBody from '../../body'
- import { UtilTools, DomTools, GlobalEvent, ResizeEvent } from '../../tools'
- import methods from './methods'
- /**
- * 渲染浮固定列
- * 分别渲染左边固定列和右边固定列
- * 如果宽度足够情况下,则不需要渲染固定列
- * @param {Function} h 创建 VNode 函数
- * @param {Object} $xetable 表格实例
- * @param {String} fixedType 固定列类型
- */
- function renderFixed (h, $xetable, fixedType) {
- const { tableData, tableColumn, visibleColumn, tableGroupColumn, isGroup, vSize, showHeader, showFooter, columnStore, footerTableData } = $xetable
- const fixedColumn = columnStore[`${fixedType}List`]
- return h('div', {
- class: `vxe-table--fixed-${fixedType}-wrapper`,
- ref: `${fixedType}Container`
- }, [
- showHeader ? h('vxe-table-header', {
- props: {
- fixedType,
- tableData,
- tableColumn,
- visibleColumn,
- tableGroupColumn,
- size: vSize,
- fixedColumn,
- isGroup
- },
- ref: `${fixedType}Header`
- }) : null,
- h('vxe-table-body', {
- props: {
- fixedType,
- tableData,
- tableColumn,
- visibleColumn,
- fixedColumn,
- size: vSize,
- isGroup
- },
- ref: `${fixedType}Body`
- }),
- showFooter && footerTableData ? h('vxe-table-footer', {
- props: {
- footerTableData,
- tableColumn,
- visibleColumn,
- fixedColumn,
- fixedType,
- size: vSize
- },
- ref: `${fixedType}Footer`
- }) : null
- ])
- }
- export default {
- name: 'VxeTable',
- props: {
- /** 基本属性 */
- id: String,
- // 数据
- data: Array,
- // (v3.0 废弃)
- customs: Array,
- // 表格的高度
- height: [Number, String],
- // 表格的最大高度
- maxHeight: [Number, String],
- // 所有列是否允许拖动列宽调整大小
- resizable: { type: Boolean, default: () => GlobalConfig.table.resizable },
- // 是否带有斑马纹
- stripe: { type: Boolean, default: () => GlobalConfig.table.stripe },
- // 是否带有边框
- border: { type: [Boolean, String], default: () => GlobalConfig.table.border },
- // 是否圆角边框
- round: { type: Boolean, default: () => GlobalConfig.table.round },
- // 表格的尺寸
- size: { type: String, default: () => GlobalConfig.table.size || GlobalConfig.size },
- // 列的宽度是否自撑开(可能会被废弃的参数,不要使用)
- fit: { type: Boolean, default: () => GlobalConfig.table.fit },
- // 表格是否加载中
- loading: Boolean,
- // 所有的列对其方式
- align: { type: String, default: () => GlobalConfig.table.align },
- // 所有的表头列的对齐方式
- headerAlign: { type: String, default: () => GlobalConfig.table.headerAlign },
- // 所有的表尾列的对齐方式
- footerAlign: { type: String, default: () => GlobalConfig.table.footerAlign },
- // 是否显示表头
- showHeader: { type: Boolean, default: () => GlobalConfig.table.showHeader },
- // (v3.0 废弃)
- startIndex: { type: Number, default: 0 },
- // 是否要高亮当前选中行
- highlightCurrentRow: { type: Boolean, default: () => GlobalConfig.table.highlightCurrentRow },
- // 鼠标移到行是否要高亮显示
- highlightHoverRow: { type: Boolean, default: () => GlobalConfig.table.highlightHoverRow },
- // 是否要高亮当前选中列
- highlightCurrentColumn: { type: Boolean, default: () => GlobalConfig.table.highlightCurrentColumn },
- // 鼠标移到列是否要高亮显示
- highlightHoverColumn: { type: Boolean, default: () => GlobalConfig.table.highlightHoverColumn },
- // 激活单元格编辑时是否高亮显示
- highlightCell: Boolean,
- // 是否显示表尾合计
- showFooter: Boolean,
- // 表尾合计的计算方法
- footerMethod: { type: Function, default: GlobalConfig.table.footerMethod },
- // 给行附加 className
- rowClassName: [String, Function],
- // 给单元格附加 className
- cellClassName: [String, Function],
- // 给表头的行附加 className
- headerRowClassName: [String, Function],
- // 给表头的单元格附加 className
- headerCellClassName: [String, Function],
- // 给表尾的行附加 className
- footerRowClassName: [String, Function],
- // 给表尾的单元格附加 className
- footerCellClassName: [String, Function],
- // 给单元格附加样式
- cellStyle: [Object, Function],
- // 给表头单元格附加样式
- headerCellStyle: [Object, Function],
- // 给表尾单元格附加样式
- footerCellStyle: [Object, Function],
- // 给行附加样式
- rowStyle: [Object, Function],
- // 给表头行附加样式
- headerRowStyle: [Object, Function],
- // 给表尾行附加样式
- footerRowStyle: [Object, Function],
- // 合并指定单元格
- mergeCells: Array,
- // 合并指定的表尾数据
- mergeFooterItems: Array,
- // 自定义合并行或列的方法
- spanMethod: Function,
- // 表尾合并行或列
- footerSpanMethod: Function,
- // 设置所有内容过长时显示为省略号
- showOverflow: { type: [Boolean, String], default: () => GlobalConfig.table.showOverflow },
- // 设置表头所有内容过长时显示为省略号
- showHeaderOverflow: { type: [Boolean, String], default: () => GlobalConfig.table.showHeaderOverflow },
- // 设置表尾所有内容过长时显示为省略号
- showFooterOverflow: { type: [Boolean, String], default: () => GlobalConfig.table.showFooterOverflow },
- // 是否所有服务端筛选
- remoteFilter: Boolean,
- // 是否所有服务端排序
- remoteSort: Boolean,
- // 自定义所有列的排序方法
- sortMethod: Function,
- // 所有列宽度
- columnWidth: [Number, String],
- // 所有列最小宽度,把剩余宽度按比例分配
- columnMinWidth: [Number, String],
- /** 高级属性 */
- // 主键配置
- columnKey: Boolean,
- rowKey: Boolean,
- rowId: { type: String, default: () => GlobalConfig.table.rowId },
- zIndex: Number,
- emptyText: { type: String, default: () => GlobalConfig.table.emptyText },
- keepSource: { type: Boolean, default: () => GlobalConfig.table.keepSource },
- // 是否自动监听父容器变化去更新响应式表格宽高
- autoResize: { type: Boolean, default: () => GlobalConfig.table.autoResize },
- // 是否自动根据状态属性去更新响应式表格宽高
- syncResize: [Boolean, String, Number],
- // 设置列的默认参数,仅对部分支持的属性有效
- columnConfig: Object,
- resizableConfig: Object,
- // 序号配置项
- seqConfig: Object,
- // 排序配置项
- sortConfig: Object,
- // 筛选配置项
- filterConfig: Object,
- // 单选框配置
- radioConfig: Object,
- // (v3.0 废弃)
- selectConfig: Object,
- // 复选框配置项
- checkboxConfig: Object,
- // tooltip 配置项
- tooltipConfig: Object,
- // 导出配置项
- exportConfig: [Boolean, Object],
- // 导入配置项
- importConfig: [Boolean, Object],
- // 打印配置项
- printConfig: Object,
- // 展开行配置项
- expandConfig: Object,
- // 树形结构配置项
- treeConfig: [Boolean, Object],
- // 快捷菜单配置项
- menuConfig: [Boolean, Object],
- // 在 v3 中废弃
- contextMenu: [Boolean, Object],
- // 鼠标配置项
- mouseConfig: Object,
- // 区域配置项
- areaConfig: Object,
- // 按键配置项
- keyboardConfig: Object,
- // 复制/粘贴配置项
- clipConfig: Object,
- // 查找/替换配置项
- fnrConfig: Object,
- // 编辑配置项
- editConfig: [Boolean, Object],
- // 校验配置项
- validConfig: Object,
- // 校验规则配置项
- editRules: Object,
- // 空内容渲染配置项
- emptyRender: [Boolean, Object],
- // 自定义列配置项
- customConfig: [Boolean, Object],
- // 横向虚拟滚动配置项
- scrollX: Object,
- // 纵向虚拟滚动配置项
- scrollY: Object,
- // 优化相关
- cloak: { type: Boolean, default: () => GlobalConfig.table.cloak },
- animat: { type: Boolean, default: () => GlobalConfig.table.animat },
- delayHover: { type: Number, default: () => GlobalConfig.table.delayHover },
- // 优化配置项
- optimization: Object,
- // 额外的参数
- params: Object
- },
- components: {
- VxeTableBody
- },
- provide () {
- return {
- $xetable: this,
- xecolgroup: null
- }
- },
- inject: {
- $xegrid: {
- default: null
- }
- },
- mixins: [],
- data () {
- return {
- tId: `${XEUtils.uniqueId()}`,
- isCloak: false,
- // 列分组配置
- collectColumn: [],
- // 渲染的列分组
- tableGroupColumn: [],
- // 完整所有列
- tableFullColumn: [],
- // 渲染所有列
- visibleColumn: [],
- // 可视区渲染的列
- tableColumn: [],
- // 渲染中的数据
- tableData: [],
- // 是否启用了横向 X 可视渲染方式加载
- scrollXLoad: false,
- // 是否启用了纵向 Y 可视渲染方式加载
- scrollYLoad: false,
- // 是否存在纵向滚动条
- overflowY: true,
- // 是否存在横向滚动条
- overflowX: false,
- // 纵向滚动条的宽度
- scrollbarWidth: 0,
- // 横向滚动条的高度
- scrollbarHeight: 0,
- // 行高
- rowHeight: 0,
- // 表格父容器的高度
- parentHeight: 0,
- // 复选框属性,是否全选
- isAllSelected: false,
- // 复选框属性,有选中且非全选状态
- isIndeterminate: false,
- // 复选框属性,已选中的行
- selection: [],
- // 当前行
- currentRow: null,
- // 单选框属性,选中列
- currentColumn: null,
- // 单选框属性,选中行
- selectRow: null,
- // 表尾合计数据
- footerTableData: [],
- // 展开列信息
- expandColumn: null,
- // 树节点列信息
- treeNodeColumn: null,
- // 已展开的行
- rowExpandeds: [],
- // 懒加载中的展开行的列表
- expandLazyLoadeds: [],
- // 已展开树节点
- treeExpandeds: [],
- // 懒加载中的树节点的列表
- treeLazyLoadeds: [],
- // 树节点不确定状态的列表
- treeIndeterminates: [],
- // 合并单元格的对象集
- mergeList: [],
- // 合并表尾数据的对象集
- mergeFooterList: [],
- // 是否已经加载了筛选
- hasFilterPanel: false,
- // 当前选中的筛选列
- filterStore: {
- isAllSelected: false,
- isIndeterminate: false,
- style: null,
- options: [],
- column: null,
- multiple: false,
- visible: false
- },
- // 存放列相关的信息
- columnStore: {
- leftList: [],
- centerList: [],
- rightList: [],
- resizeList: [],
- pxList: [],
- pxMinList: [],
- scaleList: [],
- scaleMinList: [],
- autoList: []
- },
- // 存放快捷菜单的信息
- ctxMenuStore: {
- selected: null,
- visible: false,
- showChild: false,
- selectChild: null,
- list: [],
- style: null
- },
- // 存放可编辑相关信息
- editStore: {
- indexs: {
- columns: []
- },
- titles: {
- columns: []
- },
- // 所有选中
- checked: {
- rows: [],
- columns: [],
- tRows: [],
- tColumns: []
- },
- // 选中源
- selected: {
- row: null,
- column: null
- },
- // 已复制源
- copyed: {
- cut: false,
- rows: [],
- columns: []
- },
- // 激活
- actived: {
- row: null,
- column: null
- },
- insertList: [],
- removeList: []
- },
- // 存放数据校验相关信息
- validStore: {
- visible: false,
- row: null,
- column: null,
- content: '',
- rule: null,
- isArrow: false
- },
- // 导入相关信息
- importStore: {
- file: null,
- type: '',
- modeList: [],
- typeList: [],
- filename: '',
- visible: false
- },
- importParams: {
- mode: '',
- types: null,
- message: true
- },
- // 导出相关信息
- exportStore: {
- name: '',
- modeList: [],
- typeList: [],
- columns: [],
- hasFooter: false,
- visible: false
- },
- exportParams: {
- filename: '',
- sheetName: '',
- mode: '',
- type: '',
- original: false,
- message: true,
- isHeader: false,
- isFooter: false
- }
- }
- },
- computed: {
- vSize () {
- return this.size || this.$parent.size || this.$parent.vSize
- },
- validOpts () {
- return Object.assign({ message: 'default' }, GlobalConfig.table.validConfig, this.validConfig)
- },
- sXOpts () {
- return Object.assign({}, GlobalConfig.table.scrollX, this.optimizeOpts.scrollX, this.scrollX)
- },
- sYOpts () {
- return Object.assign({}, GlobalConfig.table.scrollY, this.optimizeOpts.scrollY, this.scrollY)
- },
- optimizeOpts () {
- return Object.assign({}, GlobalConfig.table.optimization, this.optimization)
- },
- rowHeightMaps () {
- return {
- default: 48,
- medium: 44,
- small: 40,
- mini: 36
- }
- },
- columnOpts () {
- return Object.assign({}, this.columnConfig)
- },
- resizableOpts () {
- return Object.assign({}, GlobalConfig.table.resizableConfig, this.resizableConfig)
- },
- seqOpts () {
- return Object.assign({ startIndex: 0 }, GlobalConfig.table.seqConfig, this.seqConfig)
- },
- radioOpts () {
- return Object.assign({}, GlobalConfig.table.radioConfig, this.radioConfig)
- },
- checkboxOpts () {
- return Object.assign({}, GlobalConfig.table.checkboxConfig, this.checkboxConfig || this.selectConfig)
- },
- tooltipOpts () {
- return Object.assign({ size: this.vSize, leaveDelay: 300 }, GlobalConfig.table.tooltipConfig, this.tooltipConfig)
- },
- validTipOpts () {
- return Object.assign({ isArrow: false }, this.tooltipOpts)
- },
- editOpts () {
- return Object.assign({}, GlobalConfig.table.editConfig, this.editConfig)
- },
- sortOpts () {
- return Object.assign({ orders: ['asc', 'desc', null] }, GlobalConfig.table.sortConfig, this.sortConfig)
- },
- filterOpts () {
- return Object.assign({}, GlobalConfig.table.filterConfig, this.filterConfig)
- },
- mouseOpts () {
- return Object.assign({}, GlobalConfig.table.mouseConfig, this.mouseConfig)
- },
- areaOpts () {
- return Object.assign({}, GlobalConfig.table.areaConfig, this.areaConfig)
- },
- keyboardOpts () {
- return Object.assign({}, GlobalConfig.table.keyboardConfig, this.keyboardConfig)
- },
- clipOpts () {
- return Object.assign({}, GlobalConfig.table.clipConfig, this.clipConfig)
- },
- fnrOpts () {
- return Object.assign({}, GlobalConfig.table.fnrConfig, this.fnrConfig)
- },
- // 是否使用了分组表头
- isGroup () {
- return this.collectColumn.some(UtilTools.hasChildrenList)
- },
- hasTip () {
- return VXETable._tooltip
- },
- isResizable () {
- return this.resizable || this.tableFullColumn.some(column => column.resizable)
- },
- headerCtxMenu () {
- const headerOpts = this.ctxMenuOpts.header
- return headerOpts && headerOpts.options ? headerOpts.options : []
- },
- bodyCtxMenu () {
- const bodyOpts = this.ctxMenuOpts.body
- return bodyOpts && bodyOpts.options ? bodyOpts.options : []
- },
- footerCtxMenu () {
- const footerOpts = this.ctxMenuOpts.footer
- return footerOpts && footerOpts.options ? footerOpts.options : []
- },
- isCtxMenu () {
- return (this.contextMenu || this.menuConfig) && UtilTools.isEnableConf(this.ctxMenuOpts) && (this.headerCtxMenu.length || this.bodyCtxMenu.length || this.footerCtxMenu.length)
- },
- ctxMenuOpts () {
- return Object.assign({}, GlobalConfig.table.contextMenu, GlobalConfig.table.menuConfig, this.contextMenu, this.menuConfig)
- },
- ctxMenuList () {
- const rest = []
- this.ctxMenuStore.list.forEach(list => {
- list.forEach(item => {
- rest.push(item)
- })
- })
- return rest
- },
- exportOpts () {
- return Object.assign({}, GlobalConfig.table.exportConfig, this.exportConfig)
- },
- importOpts () {
- return Object.assign({}, GlobalConfig.table.importConfig, this.importConfig)
- },
- printOpts () {
- return Object.assign({}, GlobalConfig.table.printConfig, this.printConfig)
- },
- expandOpts () {
- return Object.assign({}, GlobalConfig.table.expandConfig, this.expandConfig)
- },
- treeOpts () {
- return Object.assign({}, GlobalConfig.table.treeConfig, this.treeConfig)
- },
- emptyOpts () {
- return Object.assign({}, GlobalConfig.table.emptyRender, this.emptyRender)
- },
- cellOffsetWidth () {
- return this.border ? Math.max(2, Math.ceil(this.scrollbarWidth / this.tableColumn.length)) : 1
- },
- customOpts () {
- return Object.assign({}, GlobalConfig.table.customConfig, this.customConfig)
- },
- tableBorder () {
- const { border } = this
- if (border === true) {
- return 'full'
- }
- if (border) {
- return border
- }
- return 'default'
- },
- /**
- * 判断列全选的复选框是否禁用
- */
- isAllCheckboxDisabled () {
- const { tableFullData, treeConfig, checkboxOpts } = this
- const { strict, checkMethod } = checkboxOpts
- if (strict) {
- if (tableFullData.length) {
- if (checkMethod) {
- if (treeConfig) {
- // 暂时不支持树形结构
- }
- // 如果所有行都被禁用
- return tableFullData.every((row) => !checkMethod({ row }))
- }
- return false
- }
- return true
- }
- return false
- }
- },
- watch: {
- data (value) {
- this.loadTableData(value).then(() => {
- if (!this.inited) {
- this.inited = true
- this.handleDefaults()
- }
- if ((this.scrollXLoad || this.scrollYLoad) && this.expandColumn) {
- UtilTools.warn('vxe.error.scrollErrProp', ['column.type=expand'])
- }
- })
- },
- customs (value) {
- if (!this.isUpdateCustoms) {
- this.mergeCustomColumn(value)
- }
- this.isUpdateCustoms = false
- },
- collectColumn (value) {
- const tableFullColumn = UtilTools.getColumnList(value)
- this.tableFullColumn = tableFullColumn
- this.clearMergeCells()
- this.clearMergeFooterItems()
- this.cacheColumnMap()
- if (this.customs) {
- this.mergeCustomColumn(this.customs)
- }
- if (this.customConfig) {
- this.restoreCustomStorage()
- }
- this.refreshColumn().then(() => {
- if (this.scrollXLoad) {
- this.loadScrollXData(true)
- }
- })
- this.handleTableData(true)
- if ((this.scrollXLoad || this.scrollYLoad) && this.expandColumn) {
- UtilTools.warn('vxe.error.scrollErrProp', ['column.type=expand'])
- }
- if (this.isGroup && this.mouseConfig && this.mouseOpts.checked) {
- UtilTools.error('vxe.error.groupMouseRange', ['mouse-config.checked'])
- }
- this.$nextTick(() => {
- if (this.$toolbar) {
- this.$toolbar.syncUpdate({ collectColumn: value, $table: this })
- // 在 v3.0 中废弃 toolbar 方式
- if (!this.customConfig) {
- this.restoreCustomStorage()
- this.analyColumnWidth()
- this.refreshColumn()
- }
- }
- })
- },
- tableColumn () {
- this.analyColumnWidth()
- },
- showHeader () {
- this.$nextTick(() => {
- this.recalculate(true).then(() => this.refreshScroll())
- })
- },
- showFooter () {
- this.$nextTick(() => {
- this.recalculate(true).then(() => this.refreshScroll())
- })
- },
- height () {
- this.$nextTick(() => this.recalculate(true))
- },
- maxHeight () {
- this.$nextTick(() => this.recalculate(true))
- },
- syncResize (value) {
- if (value) {
- const { $el } = this
- // 只在可视状态下才去更新
- if ($el.clientWidth && $el.clientHeight) {
- this.recalculate()
- }
- this.$nextTick(() => {
- setTimeout(() => {
- if ($el.clientWidth && $el.clientHeight) {
- this.recalculate(true)
- }
- })
- })
- }
- },
- mergeCells (value) {
- this.clearMergeCells()
- this.setMergeCells(value)
- },
- mergeFooterItems (value) {
- this.clearMergeFooterItems()
- this.setMergeFooterItems(value)
- }
- },
- created () {
- const { sXOpts, scrollXStore, sYOpts, scrollYStore, mouseOpts, data, editOpts, treeOpts, treeConfig, showOverflow } = Object.assign(this, {
- tZindex: 0,
- elemStore: {},
- // 存放横向 X 虚拟滚动相关的信息
- scrollXStore: {},
- // 存放纵向 Y 虚拟滚动相关信息
- scrollYStore: {},
- // 存放 tooltip 相关信息
- tooltipStore: {},
- // 表格宽度
- tableWidth: 0,
- // 表格高度
- tableHeight: 0,
- // 表头高度
- headerHeight: 0,
- // 表尾高度
- footerHeight: 0,
- // 当前 hover 行
- // hoverRow: null,
- // 最后滚动位置
- lastScrollLeft: 0,
- lastScrollTop: 0,
- // 单选框属性,已选中保留的行
- radioReserveRow: null,
- // 复选框属性,已选中保留的行
- checkboxReserveRowMap: {},
- // 行数据,已展开保留的行
- rowExpandedReserveRowMap: {},
- // 树结构数据,已展开保留的行
- treeExpandedReserveRowMap: {},
- // 完整数据、条件处理后
- tableFullData: [],
- afterFullData: [],
- // 缓存数据集
- fullAllDataRowMap: new Map(),
- fullAllDataRowIdData: {},
- fullDataRowMap: new Map(),
- fullDataRowIdData: {},
- fullColumnMap: new Map(),
- fullColumnIdData: {},
- fullColumnFieldData: {}
- })
- if (!this.rowId && (this.checkboxOpts.reserve || this.checkboxOpts.checkRowKeys || this.radioOpts.reserve || this.radioOpts.checkRowKey || this.expandOpts.expandRowKeys || this.treeOpts.expandRowKeys)) {
- UtilTools.warn('vxe.error.reqProp', ['row-id'])
- }
- // 在 v3.0 中废弃 column-width
- if (this.columnWidth) {
- UtilTools.warn('vxe.error.delProp', ['column-width', 'column-config.width'])
- }
- // 在 v3.0 中废弃 column-min-width
- if (this.columnMinWidth) {
- UtilTools.warn('vxe.error.delProp', ['column-min-width', 'column-config.minWidth'])
- }
- // 在 v3.0 中废弃 start-index
- if (this.startIndex) {
- UtilTools.warn('vxe.error.delProp', ['start-index', 'seq-config.startIndex'])
- }
- // 在 v3.0 中废弃 select-config
- if (this.selectConfig) {
- UtilTools.warn('vxe.error.delProp', ['select-config', 'checkbox-config'])
- }
- if (this.editConfig && editOpts.showStatus && !this.keepSource) {
- UtilTools.warn('vxe.error.reqProp', ['keep-source'])
- }
- if (treeConfig && treeOpts.line && (!this.rowKey || !showOverflow)) {
- UtilTools.warn('vxe.error.reqProp', ['row-key | show-overflow'])
- }
- if (this.showFooter && !this.footerMethod) {
- UtilTools.warn('vxe.error.reqProp', ['footer-method'])
- }
- // 在 v3.0 中废弃 customs
- if (this.customs) {
- UtilTools.warn('vxe.error.removeProp', ['customs'])
- }
- // 在 v3.0 中废弃 sort-method
- if (this.sortMethod) {
- UtilTools.warn('vxe.error.delProp', ['sort-method', 'sort-config.sortMethod'])
- }
- // 在 v3.0 中废弃 remote-sort
- if (this.remoteSort) {
- UtilTools.warn('vxe.error.delProp', ['remote-sort', 'sort-config.remote'])
- }
- // 在 v3.0 中废弃 remote-filter
- if (this.remoteFilter) {
- UtilTools.warn('vxe.error.delProp', ['remote-filter', 'filter-config.remote'])
- }
- if (!this.handleUpdateCellAreas) {
- if (this.clipConfig) {
- UtilTools.warn('vxe.error.notProp', ['clip-config'])
- }
- if (this.fnrConfig) {
- UtilTools.warn('vxe.error.notProp', ['fnr-config'])
- }
- if (this.mouseOpts.area) {
- UtilTools.error('vxe.error.notProp', ['mouse-config.area'])
- return
- }
- }
- if (mouseOpts.selected && mouseOpts.area) {
- UtilTools.error('vxe.error.errConflicts', ['mouse-config.area', 'mouse-config.selected'])
- }
- if (mouseOpts.checked && mouseOpts.area) {
- UtilTools.error('vxe.error.errConflicts', ['mouse-config.checked', 'mouse-config.area'])
- }
- // v3 中只支持对象类型
- // 在 v3.0 中废弃 context-menu
- if (this.contextMenu) {
- UtilTools.warn('vxe.error.delProp', ['context-menu', 'menu-config'])
- if (!XEUtils.isObject(this.contextMenu)) {
- UtilTools.warn('vxe.error.errProp', [`table.context-menu=${this.contextMenu}`, 'table.context-menu={}'])
- }
- }
- if (this.menuConfig && !XEUtils.isObject(this.menuConfig)) {
- UtilTools.warn('vxe.error.errProp', [`table.menu-config=${this.menuConfig}`, 'table.menu-config={}'])
- }
- if (this.exportConfig && !XEUtils.isObject(this.exportConfig)) {
- UtilTools.warn('vxe.error.errProp', [`table.export-config=${this.exportConfig}`, 'table.export-config={}'])
- }
- if (this.importConfig && !XEUtils.isObject(this.importConfig)) {
- UtilTools.warn('vxe.error.errProp', [`table.import-config=${this.importConfig}`, 'table.import-config={}'])
- }
- if (this.printConfig && !XEUtils.isObject(this.printConfig)) {
- UtilTools.warn('vxe.error.errProp', [`table.print-config=${this.printConfig}`, 'table.print-config={}'])
- }
- if (this.treeConfig && !XEUtils.isObject(this.treeConfig)) {
- UtilTools.warn('vxe.error.errProp', [`table.tree-config=${this.treeConfig}`, 'table.tree-config={}'])
- }
- if (this.customConfig && !XEUtils.isObject(this.customConfig)) {
- UtilTools.warn('vxe.error.errProp', [`table.custom-config=${this.customConfig}`, 'table.custom-config={}'])
- }
- if (this.editConfig && !XEUtils.isObject(this.editConfig)) {
- UtilTools.warn('vxe.error.errProp', [`table.edit-config=${this.editConfig}`, 'table.edit-config={}'])
- }
- if (this.emptyRender && !XEUtils.isObject(this.emptyRender)) {
- UtilTools.warn('vxe.error.errProp', [`table.empty-render=${this.emptyRender}`, 'table.empty-render={}'])
- }
- if (this.mouseConfig && this.editConfig) {
- if (mouseOpts.checked && editOpts.trigger !== 'dblclick') {
- UtilTools.warn('vxe.error.errProp', ['mouse-config.checked', 'edit-config.trigger=dblclick'])
- }
- }
- if (this.mouseOpts.area && this.checkboxOpts.range) {
- UtilTools.error('vxe.error.errConflicts', ['mouse-config.area', 'checkbox-config.range'])
- }
- if (treeConfig && this.stripe) {
- UtilTools.warn('vxe.error.noTree', ['stripe'])
- }
- // 在 v3.0 中废弃 optimization
- if (this.optimization) {
- UtilTools.warn('vxe.error.removeProp', ['optimization'])
- }
- // 废弃 optimization.cloak
- if (this.optimizeOpts.cloak) {
- UtilTools.warn('vxe.error.delProp', ['optimization.cloak', 'cloak'])
- }
- // 废弃 optimization.animat
- if (this.optimizeOpts.animat) {
- UtilTools.warn('vxe.error.delProp', ['optimization.animat', 'animat'])
- }
- // 废弃 optimization.delayHover
- if (this.optimizeOpts.delayHover) {
- UtilTools.warn('vxe.error.delProp', ['optimization.delayHover', 'delay-hover'])
- }
- // 废弃 optimization.scrollX
- if (this.optimizeOpts.scrollX) {
- UtilTools.warn('vxe.error.delProp', ['optimization.scrollX', 'scroll-x'])
- }
- // 废弃 optimization.scrollY
- if (this.optimizeOpts.scrollY) {
- UtilTools.warn('vxe.error.delProp', ['optimization.scrollY', 'scroll-y'])
- }
- const customOpts = this.customOpts
- if (!this.id && this.customConfig && (customOpts.storage === true || (customOpts.storage && customOpts.storage.resizable) || (customOpts.storage && customOpts.storage.visible))) {
- UtilTools.error('vxe.error.reqProp', ['id'])
- }
- if (this.treeConfig && this.checkboxOpts.range) {
- UtilTools.error('vxe.error.noTree', ['checkbox-config.range'])
- }
- if (this.treeConfig && this.mouseOpts.area) {
- UtilTools.error('vxe.error.noTree', ['mouse-config.area'])
- }
- // 检查是否有安装需要的模块
- let errorModuleName
- if (!VXETable._edit && this.editConfig) {
- errorModuleName = 'Edit'
- } else if (!VXETable._valid && this.editRules) {
- errorModuleName = 'Validator'
- } else if (!VXETable._keyboard && (this.checkboxOpts.range || this.keyboardConfig || this.mouseConfig)) {
- errorModuleName = 'Keyboard'
- } else if (!VXETable._export && (this.importConfig || this.exportConfig)) {
- errorModuleName = 'Export'
- }
- if (errorModuleName) {
- throw new Error(UtilTools.getLog('vxe.error.reqModule', [errorModuleName]))
- }
- Object.assign(scrollYStore, {
- startIndex: 0,
- visibleIndex: 0,
- adaptive: sYOpts.adaptive !== false,
- renderSize: XEUtils.toNumber(sYOpts.rSize),
- offsetSize: XEUtils.toNumber(sYOpts.oSize)
- })
- Object.assign(scrollXStore, {
- startIndex: 0,
- visibleIndex: 0,
- renderSize: XEUtils.toNumber(sXOpts.rSize),
- offsetSize: XEUtils.toNumber(sXOpts.oSize)
- })
- if (this.cloak) {
- this.isCloak = true
- setTimeout(() => {
- this.isCloak = false
- }, DomTools.browse ? 500 : 300)
- }
- this.loadTableData(data).then(() => {
- if (data && data.length) {
- this.inited = true
- this.handleDefaults()
- }
- this.updateStyle()
- this.recalculate()
- })
- GlobalEvent.on(this, 'paste', this.handleGlobalPasteEvent)
- GlobalEvent.on(this, 'copy', this.handleGlobalCopyEvent)
- GlobalEvent.on(this, 'cut', this.handleGlobalCutEvent)
- GlobalEvent.on(this, 'mousedown', this.handleGlobalMousedownEvent)
- GlobalEvent.on(this, 'blur', this.handleGlobalBlurEvent)
- GlobalEvent.on(this, 'mousewheel', this.handleGlobalMousewheelEvent)
- GlobalEvent.on(this, 'keydown', this.handleGlobalKeydownEvent)
- GlobalEvent.on(this, 'resize', this.handleGlobalResizeEvent)
- GlobalEvent.on(this, 'contextmenu', this.handleGlobalContextmenuEvent)
- this.preventEvent(null, 'created')
- },
- mounted () {
- const { $listeners } = this
- if (!this.menuConfig && ($listeners['menu-click'] || $listeners['cell-menu'] || $listeners['header-cell-menu'] || $listeners['footer-cell-menu'])) {
- UtilTools.warn('vxe.error.reqProp', ['menu-config'])
- }
- if (!this.tooltipConfig && ($listeners['cell-mouseenter'] || $listeners['cell-mouseleave'])) {
- UtilTools.warn('vxe.error.reqProp', ['tooltip-config'])
- }
- if (!this.tooltipConfig && (this.$listeners['cell-mouseenter'] || this.$listeners['cell-mouseleave'])) {
- UtilTools.warn('vxe.error.reqProp', ['tooltip-config'])
- }
- if (this.autoResize) {
- const resizeObserver = new ResizeEvent(() => this.recalculate(true))
- resizeObserver.observe(this.$el)
- resizeObserver.observe(this.getParentElem())
- this.$resize = resizeObserver
- }
- if (!this.$xegrid && this.customs) {
- UtilTools.warn('vxe.error.removeProp', ['customs'])
- }
- document.body.appendChild(this.$refs.tableWrapper)
- this.preventEvent(null, 'mounted')
- },
- activated () {
- this.recalculate().then(() => this.refreshScroll())
- this.preventEvent(null, 'activated')
- },
- deactivated () {
- this.preventEvent(null, 'deactivated')
- },
- beforeDestroy () {
- const tableWrapper = this.$refs.tableWrapper
- if (tableWrapper && tableWrapper.parentNode) {
- tableWrapper.parentNode.removeChild(tableWrapper)
- }
- if (this.$resize) {
- this.$resize.disconnect()
- }
- this.closeFilter()
- this.closeMenu()
- this.preventEvent(null, 'beforeDestroy')
- },
- destroyed () {
- GlobalEvent.off(this, 'paste')
- GlobalEvent.off(this, 'copy')
- GlobalEvent.off(this, 'cut')
- GlobalEvent.off(this, 'mousedown')
- GlobalEvent.off(this, 'blur')
- GlobalEvent.off(this, 'mousewheel')
- GlobalEvent.off(this, 'keydown')
- GlobalEvent.off(this, 'resize')
- GlobalEvent.off(this, 'contextmenu')
- this.preventEvent(null, 'destroyed')
- },
- render (h) {
- const {
- _e,
- $scopedSlots,
- tId,
- tableData,
- tableColumn,
- visibleColumn,
- tableGroupColumn,
- isGroup,
- isResizable,
- isCtxMenu,
- loading,
- isCloak,
- stripe,
- showHeader,
- height,
- tableBorder,
- treeOpts,
- treeConfig,
- mouseConfig,
- mouseOpts,
- vSize,
- validOpts,
- editRules,
- showFooter,
- overflowX,
- overflowY,
- scrollXLoad,
- scrollYLoad,
- scrollbarHeight,
- highlightCell,
- highlightHoverRow,
- highlightHoverColumn,
- editConfig,
- checkboxOpts,
- validTipOpts,
- tooltipOpts,
- columnStore,
- filterStore,
- ctxMenuStore,
- ctxMenuOpts,
- footerTableData,
- hasTip,
- emptyRender,
- emptyOpts
- } = this
- const { leftList, rightList } = columnStore
- let emptyContent
- if ($scopedSlots.empty) {
- emptyContent = $scopedSlots.empty.call(this, { $table: this }, h)
- } else {
- const compConf = emptyRender ? VXETable.renderer.get(emptyOpts.name) : null
- if (compConf) {
- emptyContent = compConf.renderEmpty.call(this, h, emptyOpts, { $table: this }, { $table: this })
- } else {
- emptyContent = this.emptyText || GlobalConfig.i18n('vxe.table.emptyText')
- }
- }
- return h('div', {
- class: ['vxe-table', 'vxe-table--render-default', `tid_${tId}`, vSize ? `size--${vSize}` : '', `border--${tableBorder}`, {
- 'vxe-editable': !!editConfig,
- 'show--head': showHeader,
- 'show--foot': showFooter,
- 'is--group': isGroup,
- 'has--height': height,
- 'has--tree-line': treeConfig && treeOpts.line,
- 'fixed--left': leftList.length,
- 'fixed--right': rightList.length,
- 'c--highlight': highlightCell,
- 't--animat': !!this.animat,
- 'is--round': this.round,
- 't--stripe': !treeConfig && stripe,
- 't--selected': mouseConfig && mouseOpts.selected,
- // 在 v3.0 中废弃 mouse-config.checked
- 't--checked': mouseConfig && mouseOpts.checked,
- 'is--area': mouseConfig && mouseOpts.area,
- 'row--highlight': highlightHoverRow,
- 'column--highlight': highlightHoverColumn,
- 'is--loading': isCloak || loading,
- 'is--empty': !loading && !tableData.length,
- 'scroll--y': overflowY,
- 'scroll--x': overflowX,
- 'virtual--x': scrollXLoad,
- 'virtual--y': scrollYLoad
- }],
- attrs: {
- 'x-cloak': isCloak
- }
- }, [
- /**
- * 隐藏列
- */
- h('div', {
- class: 'vxe-table-slots',
- ref: 'hideColumn'
- }, this.$slots.default),
- h('div', {
- class: 'vxe-table--main-wrapper'
- }, [
- /**
- * 主头部
- */
- showHeader ? h('vxe-table-header', {
- ref: 'tableHeader',
- props: {
- tableData,
- tableColumn,
- visibleColumn,
- tableGroupColumn,
- size: vSize,
- isGroup
- }
- }) : _e(),
- /**
- * 主内容
- */
- h('vxe-table-body', {
- ref: 'tableBody',
- props: {
- tableData,
- tableColumn,
- visibleColumn,
- size: vSize,
- isGroup
- }
- }),
- /**
- * 底部
- */
- showFooter ? h('vxe-table-footer', {
- props: {
- footerTableData,
- tableColumn,
- visibleColumn,
- size: vSize
- },
- ref: 'tableFooter'
- }) : null
- ]),
- /**
- * 左侧固定列
- */
- leftList && leftList.length && overflowX ? renderFixed(h, this, 'left') : _e(),
- /**
- * 右侧固定列
- */
- rightList && rightList.length && overflowX ? renderFixed(h, this, 'right') : _e(),
- /**
- * 空数据
- */
- h('div', {
- ref: 'emptyPlaceholder',
- class: 'vxe-table--empty-placeholder'
- }, [
- h('div', {
- class: 'vxe-table--empty-content'
- }, emptyContent)
- ]),
- /**
- * 边框线
- */
- h('div', {
- class: 'vxe-table--border-line'
- }),
- /**
- * 列宽线
- */
- isResizable ? h('div', {
- class: 'vxe-table--resizable-bar',
- style: overflowX ? {
- 'padding-bottom': `${scrollbarHeight}px`
- } : null,
- ref: 'resizeBar'
- }) : _e(),
- /**
- * 加载中
- */
- h('div', {
- class: ['vxe-table--loading vxe-loading', {
- 'is--visible': isCloak || loading
- }]
- }, [
- h('div', {
- class: 'vxe-loading--spinner'
- })
- ]),
- /**
- * 筛选
- */
- this.hasFilterPanel ? h('vxe-table-filter', {
- props: {
- filterStore
- },
- ref: 'filterWrapper'
- }) : _e(),
- /**
- * 导入
- */
- this.importConfig ? h('vxe-import-panel', {
- props: {
- defaultOptions: this.importParams,
- storeData: this.importStore
- }
- }) : _e(),
- /**
- * 导出/打印
- */
- this.exportConfig || this.printConfig ? h('vxe-export-panel', {
- props: {
- defaultOptions: this.exportParams,
- storeData: this.exportStore
- }
- }) : _e(),
- h('div', {
- class: `vxe-table${tId}-wrapper ${this.$vnode.data.staticClass || ''}`,
- ref: 'tableWrapper'
- }, [
- /**
- * 复选框-范围选择
- */
- checkboxOpts.range ? h('div', {
- class: 'vxe-table--checkbox-range',
- ref: 'checkboxRange'
- }) : _e(),
- /**
- * 快捷菜单
- */
- isCtxMenu ? h('vxe-table-context-menu', {
- props: {
- ctxMenuStore,
- ctxMenuOpts
- },
- ref: 'ctxWrapper'
- }) : _e(),
- /**
- * 公用提示
- */
- hasTip ? h('vxe-tooltip', {
- key: 'cTip',
- ref: 'commTip',
- props: {
- isArrow: false,
- enterable: false
- }
- }) : _e(),
- /**
- * 单元格溢出的提示
- */
- hasTip ? h('vxe-tooltip', {
- ref: 'tooltip',
- props: tooltipOpts,
- on: tooltipOpts.enterable ? {
- leave: this.handleTooltipLeaveEvent
- } : null
- }) : _e(),
- /**
- * 单元格校验不通过的提示
- * 仅用于一行数据时有效,多行数据使用内部的提示框
- */
- hasTip && editRules && validOpts.showMessage && (validOpts.message === 'default' ? !height : validOpts.message === 'tooltip') ? h('vxe-tooltip', {
- class: 'vxe-table--valid-error',
- props: validOpts.message === 'tooltip' || tableData.length === 1 ? validTipOpts : null,
- ref: 'validTip'
- }) : _e()
- ])
- ])
- },
- methods
- }
|