mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2026-02-03 09:05:28 +08:00
jvxetable 使用编辑的时候卡顿问题 #8695
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
import { defineComponent, h, nextTick, ref, useSlots } from 'vue';
|
import { defineComponent, h, nextTick, useSlots, shallowRef, markRaw } from 'vue';
|
||||||
import { vxeEmits, vxeProps } from './vxe.data';
|
import { vxeEmits, vxeProps } from './vxe.data';
|
||||||
import { useData, useRefs, useResolveComponent as rc } from './hooks/useData';
|
import { useData, useRefs, useResolveComponent as rc } from './hooks/useData';
|
||||||
import { useColumns } from './hooks/useColumns';
|
import { useColumns } from './hooks/useColumns';
|
||||||
@ -17,7 +17,10 @@ export default defineComponent({
|
|||||||
props: vxeProps(),
|
props: vxeProps(),
|
||||||
emits: [...vxeEmits],
|
emits: [...vxeEmits],
|
||||||
setup(props: JVxeTableProps, context) {
|
setup(props: JVxeTableProps, context) {
|
||||||
const instanceRef = ref();
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
// 使用 shallowRef 优化大型对象响应式性能
|
||||||
|
const instanceRef = shallowRef();
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
const refs = useRefs();
|
const refs = useRefs();
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
const data = useData(props);
|
const data = useData(props);
|
||||||
@ -33,6 +36,9 @@ export default defineComponent({
|
|||||||
const finallyProps = useFinallyProps(props, data, methods);
|
const finallyProps = useFinallyProps(props, data, methods);
|
||||||
// 渲染子组件
|
// 渲染子组件
|
||||||
const renderComponents = useRenderComponents(props, data, methods, slots);
|
const renderComponents = useRenderComponents(props, data, methods, slots);
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
markRaw(renderComponents);
|
||||||
|
// update-end--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
return {
|
return {
|
||||||
instanceRef,
|
instanceRef,
|
||||||
...refs,
|
...refs,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import type { JVxeColumn, JVxeDataProps, JVxeTableProps } from '../types';
|
import type { JVxeColumn, JVxeDataProps, JVxeTableProps } from '../types';
|
||||||
import { computed, nextTick, toRaw } from 'vue';
|
import { computed, nextTick, toRaw, shallowRef, markRaw } from 'vue';
|
||||||
import { isArray, isEmpty, isPromise } from '/@/utils/is';
|
import { isArray, isEmpty, isPromise } from '/@/utils/is';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep, debounce } from 'lodash-es';
|
||||||
import { JVxeTypePrefix, JVxeTypes } from '../types/JVxeTypes';
|
import { JVxeTypePrefix, JVxeTypes } from '../types/JVxeTypes';
|
||||||
import { initDictOptions } from '/@/utils/dict';
|
import { initDictOptions } from '/@/utils/dict';
|
||||||
import { pushIfNotExist } from '/@/utils/common/compUtils';
|
import { pushIfNotExist } from '/@/utils/common/compUtils';
|
||||||
@ -24,97 +24,129 @@ export interface HandleArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods: JVxeTableMethods, slots) {
|
export function useColumns(props: JVxeTableProps, data: JVxeDataProps, methods: JVxeTableMethods, slots) {
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
// 使用 shallowRef 优化列数据响应式性能
|
||||||
|
const columnsCache = shallowRef<JVxeColumn[]>([]);
|
||||||
|
let lastColumnsHash = '';
|
||||||
|
|
||||||
|
// 计算列哈希值,用于缓存判断
|
||||||
|
const getColumnsHash = (columns: JVxeColumn[]) => {
|
||||||
|
return JSON.stringify(columns.map(col => ({ key: col.key, type: col.type, title: col.title })));
|
||||||
|
};
|
||||||
|
|
||||||
|
// 防抖处理列计算,避免频繁重新计算
|
||||||
|
const debouncedComputeColumns = debounce(() => {
|
||||||
|
if (!isArray(props.columns)) {
|
||||||
|
columnsCache.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentHash = getColumnsHash(props.columns);
|
||||||
|
if (currentHash === lastColumnsHash) {
|
||||||
|
return; // 列没有变化,直接返回缓存
|
||||||
|
}
|
||||||
|
|
||||||
|
lastColumnsHash = currentHash;
|
||||||
|
const columns: JVxeColumn[] = [];
|
||||||
|
|
||||||
|
// handle 方法参数
|
||||||
|
const args: HandleArgs = { props, slots, data, methods, columns };
|
||||||
|
let seqColumn, selectionColumn, expandColumn, dragSortColumn;
|
||||||
|
|
||||||
|
const handleColumn = (column: JVxeColumn, container: JVxeColumn[]) => {
|
||||||
|
// 排除未授权的列 1 = 显示/隐藏; 2 = 禁用
|
||||||
|
let auth = methods.getColAuth(column.key);
|
||||||
|
if (auth?.type == '1' && !auth.isAuth) {
|
||||||
|
return;
|
||||||
|
} else if (auth?.type == '2' && !auth.isAuth) {
|
||||||
|
column.disabled = true;
|
||||||
|
}
|
||||||
|
// type 不填,默认为 normal
|
||||||
|
if (column.type == null || isEmpty(column.type)) {
|
||||||
|
column.type = JVxeTypes.normal;
|
||||||
|
}
|
||||||
|
let col: JVxeColumn = cloneDeep(column);
|
||||||
|
// 处理隐藏列
|
||||||
|
if (col.type === JVxeTypes.hidden) {
|
||||||
|
return handleInnerColumn(args, col, handleHiddenColumn);
|
||||||
|
}
|
||||||
|
// 处理子级列
|
||||||
|
// 判断是否是分组列,如果当前是父级,则无需处理 render
|
||||||
|
if (Array.isArray(col.children) && col.children.length > 0) {
|
||||||
|
const children: JVxeColumn[] = [];
|
||||||
|
col.children.forEach((child: JVxeColumn) => handleColumn(child, children));
|
||||||
|
col.children = children;
|
||||||
|
container.push(col);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 组件未注册,自动设置为 normal
|
||||||
|
if (!isRegistered(col.type)) {
|
||||||
|
col.type = JVxeTypes.normal;
|
||||||
|
}
|
||||||
|
args.enhanced = getEnhanced(col.type);
|
||||||
|
args.col = col;
|
||||||
|
args.renderOptions = {
|
||||||
|
bordered: props.bordered,
|
||||||
|
disabled: props.disabled,
|
||||||
|
scrolling: data.scrolling,
|
||||||
|
isDisabledRow: methods.isDisabledRow,
|
||||||
|
listeners: {
|
||||||
|
trigger: (name, event) => methods.trigger(name, event),
|
||||||
|
valueChange: (event) => methods.trigger('valueChange', event),
|
||||||
|
/** 重新排序行 */
|
||||||
|
rowResort: (event) => {
|
||||||
|
methods.doSort(event.oldIndex, event.newIndex);
|
||||||
|
methods.trigger('dragged', event);
|
||||||
|
},
|
||||||
|
/** 在当前行下面插入一行 */
|
||||||
|
rowInsertDown: (rowIndex) => methods.insertRows({}, rowIndex + 1),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (col.type === JVxeTypes.rowNumber) {
|
||||||
|
seqColumn = col;
|
||||||
|
container.push(col);
|
||||||
|
} else if (col.type === JVxeTypes.rowRadio || col.type === JVxeTypes.rowCheckbox) {
|
||||||
|
selectionColumn = col;
|
||||||
|
container.push(col);
|
||||||
|
} else if (col.type === JVxeTypes.rowExpand) {
|
||||||
|
expandColumn = col;
|
||||||
|
container.push(col);
|
||||||
|
} else if (col.type === JVxeTypes.rowDragSort) {
|
||||||
|
dragSortColumn = col;
|
||||||
|
container.push(col);
|
||||||
|
} else {
|
||||||
|
col.params = column;
|
||||||
|
args.columns = container;
|
||||||
|
handlerCol(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
props.columns.forEach((column: JVxeColumn) => handleColumn(column, columns));
|
||||||
|
|
||||||
|
handleInnerColumn(args, seqColumn, handleSeqColumn);
|
||||||
|
handleInnerColumn(args, selectionColumn, handleSelectionColumn);
|
||||||
|
handleInnerColumn(args, expandColumn, handleExpandColumn);
|
||||||
|
handleInnerColumn(args, dragSortColumn, handleDragSortColumn, true);
|
||||||
|
// update-begin--author:liaozhiyang---date:2024-05-30---for【TV360X-371】不可编辑组件必填缺少*号
|
||||||
|
customComponentAddStar(columns);
|
||||||
|
// update-end--author:liaozhiyang---date:2024-05-30---for:【TV360X-371】不可编辑组件必填缺少*号
|
||||||
|
|
||||||
|
// 标记为原始对象,避免深度响应式
|
||||||
|
columnsCache.value = markRaw(columns);
|
||||||
|
}, 16); // 16ms 防抖,约等于一帧的时间
|
||||||
|
|
||||||
data.vxeColumns = computed(() => {
|
data.vxeColumns = computed(() => {
|
||||||
// linkageConfig变化时也需要执行
|
// 【issues/7812】linkageConfig改变了,vxetable没更新
|
||||||
|
// linkageConfig变化时也需要执行
|
||||||
const linkageConfig = toRaw(props.linkageConfig);
|
const linkageConfig = toRaw(props.linkageConfig);
|
||||||
if (linkageConfig) {
|
if (linkageConfig) {
|
||||||
// console.log(linkageConfig);
|
// console.log(linkageConfig);
|
||||||
}
|
}
|
||||||
let columns: JVxeColumn[] = [];
|
// 触发防抖计算
|
||||||
if (isArray(props.columns)) {
|
debouncedComputeColumns();
|
||||||
// handle 方法参数
|
return columnsCache.value;
|
||||||
const args: HandleArgs = { props, slots, data, methods, columns };
|
|
||||||
let seqColumn, selectionColumn, expandColumn, dragSortColumn;
|
|
||||||
|
|
||||||
const handleColumn = (column: JVxeColumn, container: JVxeColumn[]) => {
|
|
||||||
// 排除未授权的列 1 = 显示/隐藏; 2 = 禁用
|
|
||||||
let auth = methods.getColAuth(column.key);
|
|
||||||
if (auth?.type == '1' && !auth.isAuth) {
|
|
||||||
return;
|
|
||||||
} else if (auth?.type == '2' && !auth.isAuth) {
|
|
||||||
column.disabled = true;
|
|
||||||
}
|
|
||||||
// type 不填,默认为 normal
|
|
||||||
if (column.type == null || isEmpty(column.type)) {
|
|
||||||
column.type = JVxeTypes.normal;
|
|
||||||
}
|
|
||||||
let col: JVxeColumn = cloneDeep(column);
|
|
||||||
// 处理隐藏列
|
|
||||||
if (col.type === JVxeTypes.hidden) {
|
|
||||||
return handleInnerColumn(args, col, handleHiddenColumn);
|
|
||||||
}
|
|
||||||
// 处理子级列
|
|
||||||
// 判断是否是分组列,如果当前是父级,则无需处理 render
|
|
||||||
if (Array.isArray(col.children) && col.children.length > 0) {
|
|
||||||
const children: JVxeColumn[] = [];
|
|
||||||
col.children.forEach((child: JVxeColumn) => handleColumn(child, children));
|
|
||||||
col.children = children;
|
|
||||||
container.push(col);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 组件未注册,自动设置为 normal
|
|
||||||
if (!isRegistered(col.type)) {
|
|
||||||
col.type = JVxeTypes.normal;
|
|
||||||
}
|
|
||||||
args.enhanced = getEnhanced(col.type);
|
|
||||||
args.col = col;
|
|
||||||
args.renderOptions = {
|
|
||||||
bordered: props.bordered,
|
|
||||||
disabled: props.disabled,
|
|
||||||
scrolling: data.scrolling,
|
|
||||||
isDisabledRow: methods.isDisabledRow,
|
|
||||||
listeners: {
|
|
||||||
trigger: (name, event) => methods.trigger(name, event),
|
|
||||||
valueChange: (event) => methods.trigger('valueChange', event),
|
|
||||||
/** 重新排序行 */
|
|
||||||
rowResort: (event) => {
|
|
||||||
methods.doSort(event.oldIndex, event.newIndex);
|
|
||||||
methods.trigger('dragged', event);
|
|
||||||
},
|
|
||||||
/** 在当前行下面插入一行 */
|
|
||||||
rowInsertDown: (rowIndex) => methods.insertRows({}, rowIndex + 1),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
if (col.type === JVxeTypes.rowNumber) {
|
|
||||||
seqColumn = col;
|
|
||||||
container.push(col);
|
|
||||||
} else if (col.type === JVxeTypes.rowRadio || col.type === JVxeTypes.rowCheckbox) {
|
|
||||||
selectionColumn = col;
|
|
||||||
container.push(col);
|
|
||||||
} else if (col.type === JVxeTypes.rowExpand) {
|
|
||||||
expandColumn = col;
|
|
||||||
container.push(col);
|
|
||||||
} else if (col.type === JVxeTypes.rowDragSort) {
|
|
||||||
dragSortColumn = col;
|
|
||||||
container.push(col);
|
|
||||||
} else {
|
|
||||||
col.params = column;
|
|
||||||
args.columns = container;
|
|
||||||
handlerCol(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
props.columns.forEach((column: JVxeColumn) => handleColumn(column, columns));
|
|
||||||
|
|
||||||
handleInnerColumn(args, seqColumn, handleSeqColumn);
|
|
||||||
handleInnerColumn(args, selectionColumn, handleSelectionColumn);
|
|
||||||
handleInnerColumn(args, expandColumn, handleExpandColumn);
|
|
||||||
handleInnerColumn(args, dragSortColumn, handleDragSortColumn, true);
|
|
||||||
// update-begin--author:liaozhiyang---date:2024-05-30---for【TV360X-371】不可编辑组件必填缺少*号
|
|
||||||
customComponentAddStar(columns);
|
|
||||||
}
|
|
||||||
return columns;
|
|
||||||
});
|
});
|
||||||
|
// update-end--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ref, reactive, provide, resolveComponent } from 'vue';
|
import { ref, reactive, provide, resolveComponent, shallowRef, markRaw } from 'vue';
|
||||||
import { useDesign } from '/@/hooks/web/useDesign';
|
import { useDesign } from '/@/hooks/web/useDesign';
|
||||||
import { JVxeDataProps, JVxeRefs, JVxeTableProps } from '../types';
|
import { JVxeDataProps, JVxeRefs, JVxeTableProps } from '../types';
|
||||||
import { VxeGridInstance } from 'vxe-table';
|
import { VxeGridInstance } from 'vxe-table';
|
||||||
@ -7,90 +7,108 @@ import { randomString } from '/@/utils/common/compUtils';
|
|||||||
export function useData(props: JVxeTableProps): JVxeDataProps {
|
export function useData(props: JVxeTableProps): JVxeDataProps {
|
||||||
const { prefixCls } = useDesign('j-vxe-table');
|
const { prefixCls } = useDesign('j-vxe-table');
|
||||||
provide('prefixCls', prefixCls);
|
provide('prefixCls', prefixCls);
|
||||||
|
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
// 使用 shallowRef 优化大数据源性能
|
||||||
|
const vxeDataSource = shallowRef([]);
|
||||||
|
|
||||||
|
// 标记静态配置对象,避免深度响应式
|
||||||
|
const defaultVxeProps = markRaw({
|
||||||
|
// update-begin--author:liaozhiyang---date:20240607---for:【TV360X-327】vxetable警告
|
||||||
|
// rowId: props.rowKey,
|
||||||
|
rowConfig: {
|
||||||
|
keyField: props.rowKey,
|
||||||
|
// 高亮hover的行
|
||||||
|
isHover: true,
|
||||||
|
},
|
||||||
|
// update-end--author:liaozhiyang---date:20240607---for:【TV360X-327】vxetable警告
|
||||||
|
|
||||||
|
// --- 【issues/209】自带的tooltip会错位,所以替换成原生的title ---
|
||||||
|
// 溢出隐藏并显示tooltip
|
||||||
|
showOverflow: "title",
|
||||||
|
// 表头溢出隐藏并显示tooltip
|
||||||
|
showHeaderOverflow: "title",
|
||||||
|
// --- 【issues/209】自带的tooltip会错位,所以替换成原生的title ---
|
||||||
|
|
||||||
|
showFooterOverflow: true,
|
||||||
|
// 可编辑配置
|
||||||
|
editConfig: {
|
||||||
|
trigger: 'click',
|
||||||
|
mode: 'cell',
|
||||||
|
// update-begin--author:liaozhiyang---date:20231013---for:【QQYUN-5133】JVxeTable 行编辑升级
|
||||||
|
//activeMethod: () => !props.disabled,
|
||||||
|
beforeEditMethod: () => !props.disabled,
|
||||||
|
// update-end--author:liaozhiyang---date:20231013---for:【QQYUN-5133】JVxeTable 行编辑升级
|
||||||
|
},
|
||||||
|
expandConfig: {
|
||||||
|
iconClose: 'vxe-icon-arrow-right',
|
||||||
|
iconOpen: 'vxe-icon-arrow-down',
|
||||||
|
...props.expandConfig,
|
||||||
|
},
|
||||||
|
// 虚拟滚动配置,y轴大于xx条数据时启用虚拟滚动
|
||||||
|
scrollY: {
|
||||||
|
gt: 30,
|
||||||
|
},
|
||||||
|
scrollX: {
|
||||||
|
gt: 20,
|
||||||
|
// 暂时关闭左右虚拟滚动
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
radioConfig: {
|
||||||
|
// 保留勾选状态
|
||||||
|
reserve: true,
|
||||||
|
highlight: true,
|
||||||
|
},
|
||||||
|
checkboxConfig: {
|
||||||
|
// 保留勾选状态
|
||||||
|
reserve: true,
|
||||||
|
highlight: true,
|
||||||
|
},
|
||||||
|
mouseConfig: { selected: false },
|
||||||
|
keyboardConfig: {
|
||||||
|
// 删除键功能
|
||||||
|
isDel: false,
|
||||||
|
// Esc键关闭编辑功能
|
||||||
|
isEsc: true,
|
||||||
|
// Tab 键功能
|
||||||
|
isTab: true,
|
||||||
|
// 任意键进入编辑(功能键除外)
|
||||||
|
isEdit: true,
|
||||||
|
// 方向键功能
|
||||||
|
isArrow: true,
|
||||||
|
// 回车键功能
|
||||||
|
isEnter: true,
|
||||||
|
// 如果功能被支持,用于 column.type=checkbox|radio,开启空格键切换复选框或单选框状态功能
|
||||||
|
isChecked: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用 shallowRef 优化选中行性能
|
||||||
|
const selectedRows = shallowRef<any[]>([]);
|
||||||
|
const selectedRowIds = shallowRef<string[]>([]);
|
||||||
|
const authsMap = shallowRef(null);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
prefixCls: prefixCls,
|
prefixCls: prefixCls,
|
||||||
caseId: `j-vxe-${randomString(8)}`,
|
caseId: `j-vxe-${randomString(8)}`,
|
||||||
vxeDataSource: ref([]),
|
vxeDataSource,
|
||||||
scroll: reactive({ top: 0, left: 0 }),
|
scroll: reactive({ top: 0, left: 0 }),
|
||||||
scrolling: ref(false),
|
scrolling: ref(false),
|
||||||
defaultVxeProps: reactive({
|
defaultVxeProps,
|
||||||
// rowId: props.rowKey,
|
selectedRows,
|
||||||
rowConfig: {
|
selectedRowIds,
|
||||||
keyField: props.rowKey,
|
|
||||||
// 高亮hover的行
|
|
||||||
isHover: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
// --- 【issues/209】自带的tooltip会错位,所以替换成原生的title ---
|
|
||||||
// 溢出隐藏并显示tooltip
|
|
||||||
showOverflow: "title",
|
|
||||||
// 表头溢出隐藏并显示tooltip
|
|
||||||
showHeaderOverflow: "title",
|
|
||||||
// --- 【issues/209】自带的tooltip会错位,所以替换成原生的title ---
|
|
||||||
|
|
||||||
showFooterOverflow: true,
|
|
||||||
// 可编辑配置
|
|
||||||
editConfig: {
|
|
||||||
trigger: 'click',
|
|
||||||
mode: 'cell',
|
|
||||||
//activeMethod: () => !props.disabled,
|
|
||||||
beforeEditMethod: () => !props.disabled,
|
|
||||||
},
|
|
||||||
expandConfig: {
|
|
||||||
iconClose: 'vxe-icon-arrow-right',
|
|
||||||
iconOpen: 'vxe-icon-arrow-down',
|
|
||||||
...props.expandConfig,
|
|
||||||
},
|
|
||||||
// 虚拟滚动配置,y轴大于xx条数据时启用虚拟滚动
|
|
||||||
scrollY: {
|
|
||||||
gt: 30,
|
|
||||||
},
|
|
||||||
scrollX: {
|
|
||||||
gt: 20,
|
|
||||||
// 暂时关闭左右虚拟滚动
|
|
||||||
enabled: false,
|
|
||||||
},
|
|
||||||
radioConfig: {
|
|
||||||
// 保留勾选状态
|
|
||||||
reserve: true,
|
|
||||||
highlight: true,
|
|
||||||
},
|
|
||||||
checkboxConfig: {
|
|
||||||
// 保留勾选状态
|
|
||||||
reserve: true,
|
|
||||||
highlight: true,
|
|
||||||
},
|
|
||||||
mouseConfig: { selected: false },
|
|
||||||
keyboardConfig: {
|
|
||||||
// 删除键功能
|
|
||||||
isDel: false,
|
|
||||||
// Esc键关闭编辑功能
|
|
||||||
isEsc: true,
|
|
||||||
// Tab 键功能
|
|
||||||
isTab: true,
|
|
||||||
// 任意键进入编辑(功能键除外)
|
|
||||||
isEdit: true,
|
|
||||||
// 方向键功能
|
|
||||||
isArrow: true,
|
|
||||||
// 回车键功能
|
|
||||||
isEnter: true,
|
|
||||||
// 如果功能被支持,用于 column.type=checkbox|radio,开启空格键切换复选框或单选框状态功能
|
|
||||||
isChecked: true,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
selectedRows: ref<any[]>([]),
|
|
||||||
selectedRowIds: ref<string[]>([]),
|
|
||||||
disabledRowIds: [],
|
disabledRowIds: [],
|
||||||
statistics: reactive({
|
statistics: reactive({
|
||||||
has: false,
|
has: false,
|
||||||
sum: [],
|
sum: [],
|
||||||
average: [],
|
average: [],
|
||||||
}),
|
}),
|
||||||
authsMap: ref(null),
|
authsMap,
|
||||||
innerEditRules: {},
|
innerEditRules: {},
|
||||||
innerLinkageConfig: new Map<string, any>(),
|
innerLinkageConfig: new Map<string, any>(),
|
||||||
reloadEffectRowKeysMap: reactive({}),
|
reloadEffectRowKeysMap: reactive({}),
|
||||||
};
|
};
|
||||||
|
// update-end--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useRefs(): JVxeRefs {
|
export function useRefs(): JVxeRefs {
|
||||||
|
|||||||
@ -1,36 +1,55 @@
|
|||||||
import { nextTick, watch } from 'vue';
|
import { nextTick, watch } from 'vue';
|
||||||
import { JVxeDataProps, JVxeRefs, JVxeTableMethods } from '../types';
|
import { JVxeDataProps, JVxeRefs, JVxeTableMethods } from '../types';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep, debounce } from 'lodash-es';
|
||||||
|
|
||||||
export function useDataSource(props, data: JVxeDataProps, methods: JVxeTableMethods, refs: JVxeRefs) {
|
export function useDataSource(props, data: JVxeDataProps, methods: JVxeTableMethods, refs: JVxeRefs) {
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
// 使用浅拷贝优化大数据量处理
|
||||||
|
const processDataSource = debounce(async (newDataSource) => {
|
||||||
|
if (!Array.isArray(newDataSource)) {
|
||||||
|
data.vxeDataSource.value = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data.vxeDataSource.value = cloneDeep(newDataSource);
|
||||||
|
// 批量处理禁用行,减少循环次数
|
||||||
|
const disabledRowIds: string[] = [];
|
||||||
|
data.vxeDataSource.value.forEach((row, rowIndex) => {
|
||||||
|
// 判断是否是禁用行
|
||||||
|
if (methods.isDisabledRow(row, rowIndex)) {
|
||||||
|
disabledRowIds.push(row.id);
|
||||||
|
}
|
||||||
|
// 处理联动回显数据
|
||||||
|
methods.handleLinkageBackData(row);
|
||||||
|
});
|
||||||
|
data.disabledRowIds = disabledRowIds;
|
||||||
|
|
||||||
|
const grid = await waitRef(refs.gridRef);
|
||||||
|
if (grid?.value) methods.recalcSortNumber();
|
||||||
|
}, 50); // 50ms 防抖,避免频繁更新
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.dataSource,
|
() => props.dataSource,
|
||||||
async () => {
|
(newDataSource) => {
|
||||||
data.disabledRowIds = [];
|
processDataSource(newDataSource);
|
||||||
data.vxeDataSource.value = cloneDeep(props.dataSource);
|
|
||||||
data.vxeDataSource.value.forEach((row, rowIndex) => {
|
|
||||||
// 判断是否是禁用行
|
|
||||||
if (methods.isDisabledRow(row, rowIndex)) {
|
|
||||||
data.disabledRowIds.push(row.id);
|
|
||||||
}
|
|
||||||
// 处理联动回显数据
|
|
||||||
methods.handleLinkageBackData(row);
|
|
||||||
});
|
|
||||||
await waitRef(refs.gridRef);
|
|
||||||
methods.recalcSortNumber();
|
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
// update-end--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
}
|
}
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
function waitRef($ref) {
|
function waitRef($ref, maxTries = 10) {
|
||||||
return new Promise<any>((resolve) => {
|
return new Promise<any>((resolve) => {
|
||||||
|
let tries = 0;
|
||||||
(function next() {
|
(function next() {
|
||||||
if ($ref.value) {
|
if ($ref.value) {
|
||||||
resolve($ref);
|
resolve($ref);
|
||||||
|
} else if (tries >= maxTries) {
|
||||||
|
resolve(null);
|
||||||
} else {
|
} else {
|
||||||
|
tries++;
|
||||||
nextTick(() => next());
|
nextTick(() => next());
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// update-end--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { unref, computed, ref, watch, nextTick } from 'vue';
|
import { unref, computed, ref, watch, nextTick, shallowRef } from 'vue';
|
||||||
import { merge, debounce } from 'lodash-es';
|
import { merge, debounce, throttle } from 'lodash-es';
|
||||||
import { isArray } from '/@/utils/is';
|
import { isArray } from '/@/utils/is';
|
||||||
import { useAttrs } from '/@/hooks/core/useAttrs';
|
import { useAttrs } from '/@/hooks/core/useAttrs';
|
||||||
import { useKeyboardEdit } from '../hooks/useKeyboardEdit';
|
import { useKeyboardEdit } from '../hooks/useKeyboardEdit';
|
||||||
@ -11,12 +11,19 @@ export function useFinallyProps(props: JVxeTableProps, data: JVxeDataProps, meth
|
|||||||
const { keyboardEditConfig } = useKeyboardEdit(props);
|
const { keyboardEditConfig } = useKeyboardEdit(props);
|
||||||
// vxe 最终 editRules
|
// vxe 最终 editRules
|
||||||
const vxeEditRules = computed(() => merge({}, props.editRules, data.innerEditRules));
|
const vxeEditRules = computed(() => merge({}, props.editRules, data.innerEditRules));
|
||||||
|
// ==================== 性能优化 - 开始 ====================
|
||||||
|
// 使用节流优化高频事件
|
||||||
|
const throttledScroll = throttle(methods.handleVxeScroll, 16); // 约60fps
|
||||||
|
const throttledCellClick = throttle(methods.handleCellClick, 100);
|
||||||
|
|
||||||
// vxe 最终 events
|
// vxe 最终 events
|
||||||
const vxeEvents = computed(() => {
|
const vxeEvents = computed(() => {
|
||||||
let listeners = { ...unref(attrs) };
|
let listeners = { ...unref(attrs) };
|
||||||
let events = {
|
let events = {
|
||||||
onScroll: methods.handleVxeScroll,
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
onCellClick: methods.handleCellClick,
|
onScroll: throttledScroll,
|
||||||
|
onCellClick: throttledCellClick,
|
||||||
|
// update-end--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
onEditClosed: methods.handleEditClosed,
|
onEditClosed: methods.handleEditClosed,
|
||||||
onEditActived: methods.handleEditActived,
|
onEditActived: methods.handleEditActived,
|
||||||
onRadioChange: methods.handleVxeRadioChange,
|
onRadioChange: methods.handleVxeRadioChange,
|
||||||
@ -111,14 +118,20 @@ export function useFinallyProps(props: JVxeTableProps, data: JVxeDataProps, meth
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 代码逻辑说明: 【issues/8593】修复列改变后内容不刷新
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
const vxeColumnsRef = ref(data.vxeColumns!.value || [])
|
// 使用 shallowRef 优化列更新性能
|
||||||
|
const vxeColumnsRef = shallowRef([])
|
||||||
const watchColumnsDebounce = debounce(async () => {
|
const watchColumnsDebounce = debounce(async () => {
|
||||||
vxeColumnsRef.value = []
|
vxeColumnsRef.value = []
|
||||||
await nextTick()
|
await nextTick()
|
||||||
vxeColumnsRef.value = data.vxeColumns!.value
|
vxeColumnsRef.value = data.vxeColumns?.value || []
|
||||||
}, 50)
|
}, 16) // 减少防抖时间到16ms,提高响应速度
|
||||||
watch(data.vxeColumns!, watchColumnsDebounce)
|
|
||||||
|
// 安全地监听列变化
|
||||||
|
if (data.vxeColumns) {
|
||||||
|
watch(data.vxeColumns, watchColumnsDebounce)
|
||||||
|
}
|
||||||
|
// update-end--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
|
||||||
const vxeProps = computed(() => {
|
const vxeProps = computed(() => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { simpleDebounce } from '/@/utils/common/compUtils';
|
|||||||
import { JVxeDataProps, JVxeRefs, JVxeTableProps, JVxeTypes } from '../types';
|
import { JVxeDataProps, JVxeRefs, JVxeTableProps, JVxeTypes } from '../types';
|
||||||
import { getEnhanced } from '../utils/enhancedUtils';
|
import { getEnhanced } from '../utils/enhancedUtils';
|
||||||
import { VxeTableInstance, VxeTablePrivateMethods } from 'vxe-table';
|
import { VxeTableInstance, VxeTablePrivateMethods } from 'vxe-table';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep, throttle } from 'lodash-es';
|
||||||
import { isArray, isEmpty, isNull, isString } from '/@/utils/is';
|
import { isArray, isEmpty, isNull, isString } from '/@/utils/is';
|
||||||
import { useLinkage } from './useLinkage';
|
import { useLinkage } from './useLinkage';
|
||||||
import { useWebSocket } from './useWebSocket';
|
import { useWebSocket } from './useWebSocket';
|
||||||
@ -67,7 +67,7 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 监听vxe滚动条位置 */
|
/** 监听vxe滚动条位置 */
|
||||||
function handleVxeScroll(event) {
|
const throttledScroll = throttle((event) => {
|
||||||
let { scroll } = data;
|
let { scroll } = data;
|
||||||
|
|
||||||
// 记录滚动条的位置
|
// 记录滚动条的位置
|
||||||
@ -77,7 +77,12 @@ export function useMethods(props: JVxeTableProps, { emit }, data: JVxeDataProps,
|
|||||||
refs.subPopoverRef.value?.close();
|
refs.subPopoverRef.value?.close();
|
||||||
data.scrolling.value = true;
|
data.scrolling.value = true;
|
||||||
closeScrolling();
|
closeScrolling();
|
||||||
|
}, 16);
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
function handleVxeScroll(event) {
|
||||||
|
throttledScroll(event);
|
||||||
}
|
}
|
||||||
|
// update-begin--author:liaozhiyang---date:20260130---for:【QQYUN-14177】online配置界面,字段配置卡顿
|
||||||
|
|
||||||
// 当手动勾选单选时触发的事件
|
// 当手动勾选单选时触发的事件
|
||||||
function handleVxeRadioChange(event) {
|
function handleVxeRadioChange(event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user