mt-ui-components-vue3
Version:
玛果添实UI组件库(Vue3)
261 lines (260 loc) • 10 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _vue = require("vue");
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));
var _lodash = require("lodash");
var _components = require("../../../components");
var Scroll = (0, _vue.defineComponent)({
name: 'Scroll',
props: {
dataSource: {
type: Array,
default: function _default() {
return [];
}
},
total: {
type: Number,
default: 0
},
windowHeight: {
// 可视高度
type: Number,
default: 500
},
bodyStyle: {
type: Object,
default: function _default() {
return {};
}
},
column: {
type: Number,
default: 4
}
},
slots: ['prev'],
emits: ['reachBottom'],
setup: function setup(props, _ref) {
var slots = _ref.slots,
emit = _ref.emit;
var windowRef = (0, _vue.ref)();
var innerRef = (0, _vue.ref)();
var itemRef = (0, _vue.ref)();
var columnSpan = 20;
var rowSpan = 20;
var windowWidth = (0, _vue.ref)(0);
var _scrollTop = (0, _vue.ref)(0);
var loading = (0, _vue.ref)(true);
var cardWidth = (0, _vue.ref)(0);
var cardHeight = (0, _vue.ref)(0);
// 每排展示的卡片数量
var totalRow = (0, _vue.computed)(function () {
return (props === null || props === void 0 ? void 0 : props.column) || 4;
}); // computed(() => Math.floor((windowWidth.value + rowSpan) / (cardWidth.value + rowSpan)))
// 总共展示的列数
var totalColumn = (0, _vue.computed)(function () {
return Math.ceil(props.total / totalRow.value);
});
var states = (0, _vue.ref)({
isScrolling: false,
scrollTop: 0,
updateRequested: false,
yAxisScrollDir: 'forward'
});
var useCache = function useCache() {
var vm = (0, _vue.getCurrentInstance)();
return (0, _vue.computed)(function () {
var _getItemStyleCache = function _getItemStyleCache(_) {
return {};
};
return (0, _lodash.memoize)(_getItemStyleCache);
});
};
var getItemStyleCache = useCache();
/**
* 计算可视区域的列
*/
var getColumnsStartIndexForOffset = function getColumnsStartIndexForOffset(scrollTop) {
return Math.max(0, Math.min(totalColumn.value - 1, Math.floor(scrollTop / (cardHeight.value + columnSpan))));
};
var getColumnsStopIndexForStartIndex = function getColumnsStopIndexForStartIndex(_ref2, startIndex, scrollTop) {
var windowHeight = _ref2.windowHeight;
var numVisibleRows = Math.ceil(windowHeight / (cardHeight.value + columnSpan));
return Math.max(0, Math.min(totalColumn.value - 1, startIndex + numVisibleRows - 1));
};
var columnsToRender = (0, _vue.computed)(function () {
var _unref = (0, _vue.unref)(states),
isScrolling = _unref.isScrolling,
yAxisScrollDir = _unref.yAxisScrollDir,
scrollTop = _unref.scrollTop;
if (totalColumn.value === 0 || totalRow.value === 0) {
return [0, 0, 0, 0];
}
var startIndex = getColumnsStartIndexForOffset(scrollTop);
var stopIndex = getColumnsStopIndexForStartIndex(props, startIndex, scrollTop);
// const cacheBackward = !isScrolling || yAxisScrollDir === 'backward' ? 2 : 1
// const cacheForward = !isScrolling || yAxisScrollDir === 'forward' ? 2 : 1
return [Math.max(0, startIndex), Math.max(0, Math.min(totalColumn.value - 1, stopIndex)), startIndex, stopIndex];
});
var emitEvents = function emitEvents() {
var _unref2 = (0, _vue.unref)(states),
isScrolling = _unref2.isScrolling,
scrollTop = _unref2.scrollTop,
updateRequested = _unref2.updateRequested,
yAxisScrollDir = _unref2.yAxisScrollDir;
if (updateRequested && isScrolling && yAxisScrollDir === 'forward' && scrollTop > 0) {
var t = scrollTop - _scrollTop.value;
if (t > cardHeight.value * 2) {
_scrollTop.value = scrollTop;
emit('reachBottom', scrollTop);
}
}
};
var getScrollDir = function getScrollDir(prev, cur) {
return prev < cur ? 'forward' : 'backward';
};
var resetIsScrolling = function resetIsScrolling() {
states.value.isScrolling = false;
(0, _vue.nextTick)(function () {
getItemStyleCache.value(-1, null, null);
});
};
var onUpdated = function onUpdated() {
var _unref3 = (0, _vue.unref)(states),
scrollLeft = _unref3.scrollLeft,
scrollTop = _unref3.scrollTop,
updateRequested = _unref3.updateRequested;
var windowElement = (0, _vue.unref)(windowRef);
if (updateRequested && windowElement) {
windowElement.scrollLeft = Math.max(0, scrollLeft);
windowElement.scrollTop = Math.max(0, scrollTop);
}
};
var onScroll = function onScroll(e) {
var _e$currentTarget = e.currentTarget,
clientHeight = _e$currentTarget.clientHeight,
clientWidth = _e$currentTarget.clientWidth,
scrollHeight = _e$currentTarget.scrollHeight,
scrollTop = _e$currentTarget.scrollTop,
scrollWidth = _e$currentTarget.scrollWidth;
var _states = (0, _vue.unref)(states);
if (_states.scrollTop === scrollTop) {
return;
}
var _scrollTop = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
states.value = (0, _objectSpread2.default)((0, _objectSpread2.default)({}, _states), {}, {
isScrolling: true,
scrollTop: _scrollTop,
updateRequested: true,
yAxisScrollDir: getScrollDir(_states.scrollTop, scrollTop)
});
(0, _vue.nextTick)(function () {
return resetIsScrolling();
});
onUpdated();
emitEvents();
};
var getTopPosition = function getTopPosition(index) {
return index * (cardHeight.value + columnSpan);
};
var getLeftPosition = function getLeftPosition(index) {
return index * (cardWidth.value + rowSpan);
};
var getItemStyle = function getItemStyle(rowIndex, columnIndex) {
var itemStyleCache = getItemStyleCache.value;
// since there was no need to introduce an nested array into cache object
// we use row,column to construct the key for indexing the map.
var key = "".concat(rowIndex, ",").concat(columnIndex);
if (itemStyleCache.hasOwnProperty(key)) {
return itemStyleCache[key];
} else {
var left = getLeftPosition(rowIndex);
var top = getTopPosition(columnIndex);
itemStyleCache[key] = {
position: 'absolute',
left: "".concat(left, "px"),
top: "".concat(top, "px"),
height: "".concat(cardHeight.value, "px"),
width: "".concat(cardWidth.value, "px")
};
return itemStyleCache[key];
}
};
var renderItems = function renderItems() {
var _unref4 = (0, _vue.unref)(columnsToRender),
_unref5 = (0, _slicedToArray2.default)(_unref4, 2),
columnStart = _unref5[0],
columnEnd = _unref5[1];
var children = [];
if (totalRow.value > 0 && totalColumn.value > 0) {
for (var column = columnStart; column <= columnEnd; column++) {
for (var row = 0; row < totalRow.value; row++) {
var _index = slots.prev ? totalRow.value * column + row - 1 : totalRow.value * column + row;
children.push((0, _vue.createVNode)("div", {
"key": "".concat(row, ":").concat(column),
"style": (0, _objectSpread2.default)({}, getItemStyle(row, column))
}, [slots.prev && row === 0 && column === 0 ? slots.prev() : props.dataSource[_index] && slots.card && slots.card(props.dataSource[_index], _index)]));
}
}
} else if (slots.prev) {
children.push((0, _vue.createVNode)("div", {
"key": "".concat(0, ":", 0),
"style": (0, _objectSpread2.default)({}, getItemStyle(0, 0))
}, [slots.prev && slots.prev()]));
}
return children;
};
(0, _vue.onMounted)(function () {
loading.value = true;
// 计算卡片的宽度和高度
if (windowRef.value) {
windowWidth.value = windowRef.value.offsetWidth || 0;
cardHeight.value = itemRef.value.offsetHeight || 0;
cardWidth.value = Math.ceil(windowWidth.value / totalRow.value - rowSpan);
loading.value = false;
}
});
return function () {
return (0, _vue.createVNode)("div", {
"class": 'wrapper',
"style": props.bodyStyle
}, [(0, _vue.createVNode)("div", {
"class": 'window',
"style": {
position: 'relative',
overflowY: 'scroll',
WebkitOverflowScrolling: 'touch',
willChange: 'transform',
height: props.windowHeight ? "".concat(props.windowHeight, "px") : '100%',
width: '100%'
},
"onScroll": onScroll,
"ref": function ref(el) {
return windowRef.value = el;
}
}, [loading.value ? (0, _vue.createVNode)("div", {
"ref": function ref(el) {
return itemRef.value = el;
}
}, [slots.card && slots.card('', 0), (0, _vue.createVNode)("div", {
"style": "clear:both; height:0;"
}, null)]) : props.dataSource.length || slots.prev ? (0, _vue.createVNode)("div", {
"ref": function ref(el) {
return innerRef.value = el;
},
"style": {
width: '100%',
height: "".concat(totalColumn.value * (cardHeight.value + columnSpan) - columnSpan, "px")
}
}, [renderItems()]) : (0, _vue.createVNode)(_components.Empty, null, null)])]);
};
}
});
var _default2 = Scroll;
exports.default = _default2;