vxe-table-demonic
Version:
一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...
388 lines (387 loc) • 12.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _vue = require("vue");
var _xeUtils = _interopRequireDefault(require("xe-utils"));
var _conf = _interopRequireDefault(require("../../v-x-e-table/src/conf"));
var _size = require("../../hooks/size");
var _resize = require("../../tools/resize");
var _dom = require("../../tools/dom");
var _event = require("../../tools/event");
var _index = _interopRequireDefault(require("../../loading/index"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _default = (0, _vue.defineComponent)({
name: 'VxeList',
props: {
data: Array,
height: [Number, String],
maxHeight: [Number, String],
loading: Boolean,
className: [String, Function],
size: {
type: String,
default: function () {
return _conf.default.list.size || _conf.default.size;
}
},
autoResize: {
type: Boolean,
default: function () {
return _conf.default.list.autoResize;
}
},
syncResize: [Boolean, String, Number],
scrollY: Object
},
emits: ['scroll'],
setup: function (props, context) {
var slots = context.slots,
emit = context.emit;
var xID = _xeUtils.default.uniqueId();
var computeSize = (0, _size.useSize)(props);
var reactData = (0, _vue.reactive)({
scrollYLoad: false,
bodyHeight: 0,
rowHeight: 0,
topSpaceHeight: 0,
items: []
});
var refElem = (0, _vue.ref)();
var refVirtualWrapper = (0, _vue.ref)();
var refVirtualBody = (0, _vue.ref)();
var internalData = {
fullData: [],
lastScrollLeft: 0,
lastScrollTop: 0,
scrollYStore: {
startIndex: 0,
endIndex: 0,
visibleSize: 0,
offsetSize: 0,
rowHeight: 0
}
};
var refMaps = {
refElem: refElem
};
var $xelist = {
xID: xID,
props: props,
context: context,
reactData: reactData,
internalData: internalData,
getRefMaps: function () {
return refMaps;
}
};
var listMethods = {};
var computeSYOpts = (0, _vue.computed)(function () {
return Object.assign({}, _conf.default.list.scrollY, props.scrollY);
});
var computeStyles = (0, _vue.computed)(function () {
var height = props.height,
maxHeight = props.maxHeight;
var style = {};
if (height) {
style.height = "".concat(isNaN(height) ? height : "".concat(height, "px"));
} else if (maxHeight) {
style.height = 'auto';
style.maxHeight = "".concat(isNaN(maxHeight) ? maxHeight : "".concat(maxHeight, "px"));
}
return style;
});
var updateYSpace = function () {
var scrollYLoad = reactData.scrollYLoad;
var scrollYStore = internalData.scrollYStore,
fullData = internalData.fullData;
reactData.bodyHeight = scrollYLoad ? fullData.length * scrollYStore.rowHeight : 0;
reactData.topSpaceHeight = scrollYLoad ? Math.max(scrollYStore.startIndex * scrollYStore.rowHeight, 0) : 0;
};
var handleData = function () {
var scrollYLoad = reactData.scrollYLoad;
var fullData = internalData.fullData,
scrollYStore = internalData.scrollYStore;
reactData.items = scrollYLoad ? fullData.slice(scrollYStore.startIndex, scrollYStore.endIndex) : fullData.slice(0);
return (0, _vue.nextTick)();
};
var updateYData = function () {
handleData();
updateYSpace();
};
var computeScrollLoad = function () {
return (0, _vue.nextTick)().then(function () {
var scrollYLoad = reactData.scrollYLoad;
var scrollYStore = internalData.scrollYStore;
var virtualBodyElem = refVirtualBody.value;
var sYOpts = computeSYOpts.value;
var rowHeight = 0;
var firstItemElem;
if (virtualBodyElem) {
if (sYOpts.sItem) {
firstItemElem = virtualBodyElem.querySelector(sYOpts.sItem);
}
if (!firstItemElem) {
firstItemElem = virtualBodyElem.children[0];
}
}
if (firstItemElem) {
rowHeight = firstItemElem.offsetHeight;
}
rowHeight = Math.max(20, rowHeight);
scrollYStore.rowHeight = rowHeight;
// 计算 Y 逻辑
if (scrollYLoad) {
var scrollBodyElem = refVirtualWrapper.value;
var visibleYSize = Math.max(8, Math.ceil(scrollBodyElem.clientHeight / rowHeight));
var offsetYSize = sYOpts.oSize ? _xeUtils.default.toNumber(sYOpts.oSize) : _dom.browse.edge ? 10 : 0;
scrollYStore.offsetSize = offsetYSize;
scrollYStore.visibleSize = visibleYSize;
scrollYStore.endIndex = Math.max(scrollYStore.startIndex, visibleYSize + offsetYSize, scrollYStore.endIndex);
updateYData();
} else {
updateYSpace();
}
reactData.rowHeight = rowHeight;
});
};
/**
* 清除滚动条
*/
var clearScroll = function () {
var scrollBodyElem = refVirtualWrapper.value;
if (scrollBodyElem) {
scrollBodyElem.scrollTop = 0;
}
return (0, _vue.nextTick)();
};
/**
* 如果有滚动条,则滚动到对应的位置
* @param {Number} scrollLeft 左距离
* @param {Number} scrollTop 上距离
*/
var scrollTo = function (scrollLeft, scrollTop) {
var scrollBodyElem = refVirtualWrapper.value;
if (_xeUtils.default.isNumber(scrollLeft)) {
scrollBodyElem.scrollLeft = scrollLeft;
}
if (_xeUtils.default.isNumber(scrollTop)) {
scrollBodyElem.scrollTop = scrollTop;
}
if (reactData.scrollYLoad) {
return new Promise(function (resolve) {
setTimeout(function () {
(0, _vue.nextTick)(function () {
resolve();
});
}, 50);
});
}
return (0, _vue.nextTick)();
};
/**
* 刷新滚动条
*/
var refreshScroll = function () {
var lastScrollLeft = internalData.lastScrollLeft,
lastScrollTop = internalData.lastScrollTop;
return clearScroll().then(function () {
if (lastScrollLeft || lastScrollTop) {
internalData.lastScrollLeft = 0;
internalData.lastScrollTop = 0;
return scrollTo(lastScrollLeft, lastScrollTop);
}
});
};
/**
* 重新计算列表
*/
var recalculate = function () {
var el = refElem.value;
if (el.clientWidth && el.clientHeight) {
return computeScrollLoad();
}
return Promise.resolve();
};
var loadYData = function (evnt) {
var scrollYStore = internalData.scrollYStore;
var startIndex = scrollYStore.startIndex,
endIndex = scrollYStore.endIndex,
visibleSize = scrollYStore.visibleSize,
offsetSize = scrollYStore.offsetSize,
rowHeight = scrollYStore.rowHeight;
var scrollBodyElem = evnt.target;
var scrollTop = scrollBodyElem.scrollTop;
var toVisibleIndex = Math.floor(scrollTop / rowHeight);
var offsetStartIndex = Math.max(0, toVisibleIndex - 1 - offsetSize);
var offsetEndIndex = toVisibleIndex + visibleSize + offsetSize;
if (toVisibleIndex <= startIndex || toVisibleIndex >= endIndex - visibleSize - 1) {
if (startIndex !== offsetStartIndex || endIndex !== offsetEndIndex) {
scrollYStore.startIndex = offsetStartIndex;
scrollYStore.endIndex = offsetEndIndex;
updateYData();
}
}
};
var scrollEvent = function (evnt) {
var scrollBodyElem = evnt.target;
var scrollTop = scrollBodyElem.scrollTop;
var scrollLeft = scrollBodyElem.scrollLeft;
var isX = scrollLeft !== internalData.lastScrollLeft;
var isY = scrollTop !== internalData.lastScrollTop;
internalData.lastScrollTop = scrollTop;
internalData.lastScrollLeft = scrollLeft;
if (reactData.scrollYLoad) {
loadYData(evnt);
}
listMethods.dispatchEvent('scroll', {
scrollLeft: scrollLeft,
scrollTop: scrollTop,
isX: isX,
isY: isY
}, evnt);
};
listMethods = {
dispatchEvent: function (type, params, evnt) {
emit(type, Object.assign({
$list: $xelist,
$event: evnt
}, params));
},
/**
* 加载数据
* @param {Array} datas 数据
*/
loadData: function (datas) {
var scrollYStore = internalData.scrollYStore;
var sYOpts = computeSYOpts.value;
var fullData = datas || [];
Object.assign(scrollYStore, {
startIndex: 0,
endIndex: 1,
visibleSize: 0
});
internalData.fullData = fullData;
// 如果gt为0,则总是启用
reactData.scrollYLoad = !!sYOpts.enabled && sYOpts.gt > -1 && (sYOpts.gt === 0 || sYOpts.gt <= fullData.length);
handleData();
return computeScrollLoad().then(function () {
refreshScroll();
});
},
/**
* 重新加载数据
* @param {Array} datas 数据
*/
reloadData: function (datas) {
clearScroll();
return listMethods.loadData(datas);
},
recalculate: recalculate,
scrollTo: scrollTo,
refreshScroll: refreshScroll,
clearScroll: clearScroll
};
Object.assign($xelist, listMethods);
var dataFlag = (0, _vue.ref)(0);
(0, _vue.watch)(function () {
return props.data ? props.data.length : -1;
}, function () {
dataFlag.value++;
});
(0, _vue.watch)(function () {
return props.data;
}, function () {
dataFlag.value++;
});
(0, _vue.watch)(dataFlag, function () {
listMethods.loadData(props.data || []);
});
(0, _vue.watch)(function () {
return props.syncResize;
}, function (value) {
if (value) {
recalculate();
(0, _vue.nextTick)(function () {
return setTimeout(function () {
return recalculate();
});
});
}
});
(0, _vue.onActivated)(function () {
recalculate().then(function () {
return refreshScroll();
});
});
var resizeObserver;
(0, _vue.nextTick)(function () {
_event.GlobalEvent.on($xelist, 'resize', function () {
recalculate();
});
if (props.autoResize) {
var el = refElem.value;
resizeObserver = (0, _resize.createResizeEvent)(function () {
return recalculate();
});
resizeObserver.observe(el);
}
listMethods.loadData(props.data || []);
});
(0, _vue.onUnmounted)(function () {
if (resizeObserver) {
resizeObserver.disconnect();
}
_event.GlobalEvent.off($xelist, 'resize');
});
var renderVN = function () {
var _a;
var className = props.className,
loading = props.loading;
var bodyHeight = reactData.bodyHeight,
topSpaceHeight = reactData.topSpaceHeight,
items = reactData.items;
var vSize = computeSize.value;
var styles = computeStyles.value;
return (0, _vue.h)('div', {
ref: refElem,
class: ['vxe-list', className ? _xeUtils.default.isFunction(className) ? className({
$list: $xelist
}) : className : '', (_a = {}, _a["size--".concat(vSize)] = vSize, _a['is--loading'] = loading, _a)]
}, [(0, _vue.h)('div', {
ref: refVirtualWrapper,
class: 'vxe-list--virtual-wrapper',
style: styles,
onScroll: scrollEvent
}, [(0, _vue.h)('div', {
class: 'vxe-list--y-space',
style: {
height: bodyHeight ? "".concat(bodyHeight, "px") : ''
}
}), (0, _vue.h)('div', {
ref: refVirtualBody,
class: 'vxe-list--body',
style: {
marginTop: topSpaceHeight ? "".concat(topSpaceHeight, "px") : ''
}
}, slots.default ? slots.default({
items: items,
$list: $xelist
}) : [])]),
/**
* 加载中
*/
(0, _vue.h)(_index.default, {
class: 'vxe-list--loading',
modelValue: loading
})]);
};
$xelist.renderVN = renderVN;
return $xelist;
},
render: function () {
return this.renderVN();
}
});
exports.default = _default;