mt-ui-components-vue3
Version:
玛果添实UI组件库(Vue3)
254 lines • 9.46 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
import { createVNode as _createVNode } from "vue";
import { defineComponent, nextTick, onMounted, ref, computed, unref, getCurrentInstance } from 'vue';
import { memoize } from 'lodash';
import { Empty } from '../../../components';
var Scroll = 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 = ref();
var innerRef = ref();
var itemRef = ref();
var columnSpan = 20;
var rowSpan = 20;
var windowWidth = ref(0);
var _scrollTop = ref(0);
var loading = ref(true);
var cardWidth = ref(0);
var cardHeight = ref(0);
// 每排展示的卡片数量
var totalRow = computed(function () {
return (props === null || props === void 0 ? void 0 : props.column) || 4;
}); // computed(() => Math.floor((windowWidth.value + rowSpan) / (cardWidth.value + rowSpan)))
// 总共展示的列数
var totalColumn = computed(function () {
return Math.ceil(props.total / totalRow.value);
});
var states = ref({
isScrolling: false,
scrollTop: 0,
updateRequested: false,
yAxisScrollDir: 'forward'
});
var useCache = function useCache() {
var vm = getCurrentInstance();
return computed(function () {
var _getItemStyleCache = function _getItemStyleCache(_) {
return {};
};
return 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 = computed(function () {
var _unref = 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 = 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;
nextTick(function () {
getItemStyleCache.value(-1, null, null);
});
};
var onUpdated = function onUpdated() {
var _unref3 = unref(states),
scrollLeft = _unref3.scrollLeft,
scrollTop = _unref3.scrollTop,
updateRequested = _unref3.updateRequested;
var windowElement = 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 = unref(states);
if (_states.scrollTop === scrollTop) {
return;
}
var _scrollTop = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
states.value = _objectSpread(_objectSpread({}, _states), {}, {
isScrolling: true,
scrollTop: _scrollTop,
updateRequested: true,
yAxisScrollDir: getScrollDir(_states.scrollTop, scrollTop)
});
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 = unref(columnsToRender),
_unref5 = _slicedToArray(_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(_createVNode("div", {
"key": "".concat(row, ":").concat(column),
"style": _objectSpread({}, 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(_createVNode("div", {
"key": "".concat(0, ":", 0),
"style": _objectSpread({}, getItemStyle(0, 0))
}, [slots.prev && slots.prev()]));
}
return children;
};
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 _createVNode("div", {
"class": 'wrapper',
"style": props.bodyStyle
}, [_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 ? _createVNode("div", {
"ref": function ref(el) {
return itemRef.value = el;
}
}, [slots.card && slots.card('', 0), _createVNode("div", {
"style": "clear:both; height:0;"
}, null)]) : props.dataSource.length || slots.prev ? _createVNode("div", {
"ref": function ref(el) {
return innerRef.value = el;
},
"style": {
width: '100%',
height: "".concat(totalColumn.value * (cardHeight.value + columnSpan) - columnSpan, "px")
}
}, [renderItems()]) : _createVNode(Empty, null, null)])]);
};
}
});
export default Scroll;