mealcomes
Version:
MealComes 用于学习前端的组件库
255 lines (254 loc) • 5.54 kB
JavaScript
import { w as z } from "./utils-aznwSRCL.mjs";
import { defineComponent as k, ref as b, onMounted as F, onUpdated as B, createVNode as I, onBeforeMount as K, h as V } from "vue";
const H = {
/**
* 数据源
*/
dataSource: {
type: Array,
required: !0,
default: () => []
},
/**
* 每一项数据的 key
*/
dataKey: {
type: String,
required: !0
},
/**
* 渲染多少条数据 (存在真实 dom)
*/
keeps: {
type: Number,
default: 30
},
/**
* 每一条数据预估高度
*/
estimatedRowHeight: {
type: Number,
default: 80
},
/**
* 每一行的数据组件
*/
dataComponent: {
type: [Object, Function],
required: !0
},
/**
* 数据渲染缓冲区 (基于视口顶部 top 的数据所在位置, top ~ top + cache 为缓冲区)
*
* start = 10 cache = 5 end = 20
* - 向下滚动时, 当 top 处于 10 ~ 15, 不做处理,
* 当 top > 15, 将 start 赋为 15, 从而 end = 25(即往后渲染 cache 条数据)
* - 向上滚动时, 当 top 处于 10 ~ 15, 不做处理,
* 当 top < 10, 将 start 赋为 5, 从而 end = 15(即往前渲染 cache 条数据)
*/
cache: {
type: Number,
default: 2
}
}, O = {
uniqueKey: {
type: [String, Number],
required: !0
},
source: {
type: Object,
required: !0
},
component: {
type: [Object, Function]
}
}, C = {
itemResize: (t, l) => typeof l == "number" && (typeof t == "number" || typeof t == "string")
};
function E(t, l) {
const r = {
start: 0,
end: 0,
padBehind: 0,
padFront: 0
};
let a = 0;
const c = /* @__PURE__ */ new Map();
let s = "init", f = 0, S;
function m() {
return s === "fixed";
}
function p() {
return m() ? f : S || t.estimatedRowHeight;
}
function i(e) {
if (!e) return 0;
let n = 0;
for (let u = 0; u < e; u++) {
const o = c.get(t.uniqueIds[u]);
n += typeof o == "number" ? o : p();
}
return n;
}
function d() {
return m() ? p() * r.start : i(r.start);
}
function h() {
return (t.uniqueIds.length - 1 - r.end) * p();
}
function R(e, n) {
r.start = e, r.end = n, r.padFront = d(), r.padBehind = h(), l({ ...r });
}
function y(e, n) {
const u = t.uniqueIds.length, o = t.keeps;
u < o ? (e = 0, n = u - 1) : n - e < o - 1 && (e = n - o + 1), R(e, n);
}
function q() {
if (m())
return Math.floor(a / p());
{
let e = 0, n = t.uniqueIds.length, u = 0, o = 0;
for (; e < n; ) {
if (u = e + Math.floor((n - e) / 2), o = i(u), o === a)
return u;
o < a ? e = u + 1 : n = u - 1;
}
return e > 0 ? --e : 0;
}
}
function g(e) {
const n = e + t.keeps - 1;
return Math.min(n, t.uniqueIds.length - 1);
}
function v() {
const e = q();
if (e > r.start)
return;
const n = Math.max(0, e - t.cache);
y(n, g(n));
}
function x() {
const e = q();
e < r.start + t.cache || y(e, g(e));
}
function M(e) {
const n = e < a ? "front" : "behind";
a = e, n === "front" ? v() : n === "behind" && x();
}
function w(e, n) {
c.set(e, n), s === "init" ? (f = n, s = "fixed") : s === "fixed" && f !== n && (s = "dynamic", f = 0), s === "dynamic" && c.size < Math.min(t.keeps, t.uniqueIds.length) && (S = Math.round(
[...c.values()].reduce((u, o) => u + o, 0) / c.size
));
}
return y(0, t.keeps - 1), {
handleScroll: M,
saveSize: w
};
}
const N = /* @__PURE__ */ k({
name: "virtual-item",
props: O,
emits: C,
setup(t, {
emit: l
}) {
const r = b();
function a() {
l("itemResize", t.uniqueKey, r.value.offsetHeight);
}
return F(() => {
a();
}), B(() => {
a();
}), () => {
const {
component: c,
source: s,
uniqueKey: f
} = t;
return c && I("div", {
key: f,
ref: r
}, [I(c, {
source: s
}, null)]);
};
}
}), P = /* @__PURE__ */ k({
name: "mc-virtual-scroll-list",
props: H,
setup(t) {
const l = b(null);
let r;
const a = () => {
const {
dataSource: i,
dataKey: d
} = t;
return i.map((h) => h[d]);
}, c = (i) => {
l.value = i;
}, s = () => {
r = E({
keeps: t.keeps,
cache: t.cache || Math.round(t.keeps / 3),
uniqueIds: a(),
estimatedRowHeight: t.estimatedRowHeight
}, c);
};
K(() => {
s();
});
function f(i, d) {
r.saveSize(i, d);
}
function S() {
const i = [], {
start: d,
end: h
} = l.value, {
dataSource: R,
dataComponent: y,
dataKey: q
} = t;
for (let g = d; g <= h; g++) {
const v = R[g], x = v[q];
v && i.push(V(N, {
uniqueKey: x,
source: v,
component: y,
onItemResize: f
}));
}
return i;
}
const m = b();
function p() {
if (m.value) {
const i = m.value.scrollTop;
r.handleScroll(i);
}
}
return () => {
const {
padFront: i,
padBehind: d
} = l.value, h = {
padding: `${i}px 0 ${d}px`
};
return I("div", {
onScroll: p,
ref: m,
style: {
overflowY: "scroll"
}
}, [I("div", {
style: h
}, [S()])]);
};
}
}), L = z(P);
export {
L as M
};
//# sourceMappingURL=virtual-scroll-list-otmacS0b.mjs.map