UNPKG

vxe-table-demonic

Version:

一个基于 vue 的 PC 端表单/表格组件,支持增删改查、虚拟列表、虚拟树、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、弹窗、自定义模板、渲染器、JSON 配置式...

388 lines (387 loc) 12.5 kB
"use strict"; 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;