nutui-taro-upgrade
Version:
@nutui/nutui-taro 对京东风格组件库的taro4 版本支持
326 lines (325 loc) • 11 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
import { ref, reactive, computed, watch, toRefs, resolveComponent, openBlock, createBlock, normalizeStyle, withCtx, createElementVNode, createTextVNode, createElementBlock, Fragment, renderList, renderSlot } from "vue";
import { c as createComponent } from "../component-669c158a.js";
import Taro from "@tarojs/taro";
import { _ as _sfc_main$1 } from "../index.taro.vue_vue_type_script_setup_true_lang-1aa3f6fa.js";
import { u as useTaroRect } from "../index-d9b20e11.js";
import { _ as _export_sfc } from "../_plugin-vue_export-helper-cc2b3d55.js";
var CompareResult = /* @__PURE__ */ ((CompareResult2) => {
CompareResult2[CompareResult2["eq"] = 1] = "eq";
CompareResult2[CompareResult2["lt"] = 2] = "lt";
CompareResult2[CompareResult2["gt"] = 3] = "gt";
return CompareResult2;
})(CompareResult || {});
function binarySearch(list, value, compareFunc) {
let start = 0;
let end = list.length - 1;
let tempIndex = null;
while (start <= end) {
tempIndex = Math.floor((start + end) / 2);
const midValue = list[tempIndex];
const compareRes = compareFunc(midValue, value);
if (compareRes === 1) {
return tempIndex;
}
if (compareRes === 2) {
start = tempIndex + 1;
} else if (compareRes === 3) {
end = tempIndex - 1;
}
}
return tempIndex;
}
const { create } = createComponent("list");
const _sfc_main = create({
components: {
NutScrollView: _sfc_main$1
},
props: {
height: {
type: [Number],
default: 50
},
listData: {
type: Array,
default: () => {
return [];
}
},
bufferSize: {
type: Number,
default: 5
},
containerHeight: {
type: Number
},
estimateRowHeight: {
type: Number,
default: 80
},
margin: {
type: Number,
default: 10
}
},
emits: ["scrollUp", "scrollDown", "scrollBottom"],
setup(props, { emit }) {
var _a, _b, _c;
const clientHeight = ((_c = (_b = (_a = Taro).getSystemInfoSync) == null ? void 0 : _b.call(_a)) == null ? void 0 : _c.windowHeight) || 667;
const list = ref(null);
const phantom = ref(null);
const actualContent = ref(null);
const refRandomId = Math.random().toString(36).slice(-8);
const state = reactive({
start: 0,
originStartIndex: 0,
scrollTop: 0,
list: props.listData.slice(),
cachePositions: [],
phantomHeight: props.estimateRowHeight * props.listData.length
});
const getContainerHeight = computed(() => {
if (props.containerHeight) {
return Math.min(props.containerHeight, clientHeight);
}
return clientHeight;
});
const visibleCount = computed(() => {
return Math.ceil(getContainerHeight.value / props.estimateRowHeight);
});
const end = computed(() => {
return Math.min(state.originStartIndex + visibleCount.value + props.bufferSize, state.list.length);
});
const visibleData = computed(() => {
return state.list.slice(state.start, end.value);
});
const getTransform = () => {
if (actualContent.value) {
return `translate3d(0, ${state.start >= 1 ? state.cachePositions[state.start - 1].bottom : 0}px, 0)`;
}
};
const initCachedPosition = () => {
state.cachePositions = [];
for (let i = 0; i < state.list.length; ++i) {
state.cachePositions[i] = {
index: i,
height: props.estimateRowHeight,
top: i * props.estimateRowHeight,
bottom: (i + 1) * (props.estimateRowHeight + props.margin),
dValue: 0
};
}
};
const updateCachedPosition = () => {
let nodes = actualContent.value.childNodes;
nodes = Array.from(nodes).filter((node) => node.nodeType === 1);
const start = nodes[0];
nodes.forEach((node, index) => __async(this, null, function* () {
if (!node)
return;
useTaroRect(node).then(
(rect) => {
if (rect && rect.height) {
const { height: height2 } = rect;
const oldHeight = state.cachePositions[index + state.start] ? state.cachePositions[index + state.start].height : props.height;
const dValue = oldHeight - height2;
if (dValue && state.cachePositions[index + state.start]) {
state.cachePositions[index + state.start].bottom -= dValue;
state.cachePositions[index + state.start].height = height2;
state.cachePositions[index + state.start].dValue = dValue;
}
}
},
() => {
}
);
}));
let startIndex = 0;
if (start) {
startIndex = state.start;
}
const cachedPositionsLen = state.cachePositions.length;
let cumulativeDiffHeight = state.cachePositions[startIndex].dValue;
state.cachePositions[startIndex].dValue = 0;
for (let i = startIndex + 1; i < cachedPositionsLen; ++i) {
const item = state.cachePositions[i];
state.cachePositions[i].top = state.cachePositions[i - 1].bottom;
state.cachePositions[i].bottom = state.cachePositions[i].bottom - cumulativeDiffHeight;
if (item.dValue !== 0) {
cumulativeDiffHeight += item.dValue;
item.dValue = 0;
}
}
const height = state.cachePositions[cachedPositionsLen - 1].bottom;
state.phantomHeight = height;
};
const getStartIndex = (scrollTop = 0) => {
let idx = binarySearch(
state.cachePositions,
scrollTop,
(currentValue, targetValue) => {
const currentCompareValue = currentValue.bottom;
if (currentCompareValue === targetValue) {
return CompareResult.eq;
}
if (currentCompareValue < targetValue) {
return CompareResult.lt;
}
return CompareResult.gt;
}
);
const targetItem = state.cachePositions[idx];
if (targetItem.bottom < scrollTop) {
idx += 1;
}
return idx;
};
const resetAllVirtualParam = () => {
state.originStartIndex = 0;
state.start = 0;
state.scrollTop = 0;
list.value.scrollTop = 0;
initCachedPosition();
state.phantomHeight = props.estimateRowHeight * state.list.length;
};
const handleScrollEvent = (e) => __async(this, null, function* () {
const scrollTop = Math.max(e.detail ? e.detail.scrollTop : e.target.scrollTop, 0.1);
const { originStartIndex } = state;
const currentIndex = getStartIndex(scrollTop);
if (currentIndex !== originStartIndex) {
state.originStartIndex = currentIndex;
state.start = Math.max(state.originStartIndex - props.bufferSize, 0);
if (end.value >= state.list.length - 1) {
emit("scrollBottom");
}
}
emit(scrollTop > state.scrollTop ? "scrollUp" : "scrollDown", scrollTop);
state.scrollTop = scrollTop;
});
initCachedPosition();
watch(
() => props.listData,
(val) => {
state.list = val.slice();
if (state.list.length === val.length) {
setTimeout(() => {
initCachedPosition();
updateCachedPosition();
}, 200);
} else {
resetAllVirtualParam();
return;
}
}
);
watch(
() => state.start,
() => {
if (actualContent.value && state.list.length > 0) {
Taro.nextTick(() => {
setTimeout(() => {
updateCachedPosition();
}, 200);
});
}
}
);
return __spreadProps(__spreadValues({}, toRefs(state)), {
list,
phantom,
actualContent,
getTransform,
visibleData,
refRandomId,
getContainerHeight,
handleScrollEvent
});
}
});
const _hoisted_1 = ["id"];
const _hoisted_2 = ["id"];
const _hoisted_3 = ["id"];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_nut_scroll_view = resolveComponent("nut-scroll-view");
return openBlock(), createBlock(_component_nut_scroll_view, {
id: "list" + _ctx.refRandomId,
ref: "list",
class: "nut-list",
"scroll-y": true,
style: normalizeStyle({ height: `${_ctx.getContainerHeight}px` }),
"scroll-top": "0",
onScroll: _ctx.handleScrollEvent
}, {
default: withCtx(() => [
createElementVNode("div", {
id: "phantom" + _ctx.refRandomId,
ref: "phantom",
class: "nut-list-phantom",
style: normalizeStyle({ height: _ctx.phantomHeight + "px" })
}, null, 12, _hoisted_1),
_cache[0] || (_cache[0] = createTextVNode()),
createElementVNode("div", {
id: "actualContent" + _ctx.refRandomId,
ref: "actualContent",
class: "nut-list-container",
style: normalizeStyle({ transform: _ctx.getTransform() })
}, [
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.visibleData, (item, index) => {
return openBlock(), createElementBlock("div", {
id: "list-item-" + Number(index + _ctx.start),
key: item,
class: "nut-list-item"
}, [
renderSlot(_ctx.$slots, "default", {
item,
index: index + _ctx.start
})
], 8, _hoisted_3);
}), 128))
], 12, _hoisted_2)
]),
_: 3
}, 8, ["id", "style", "onScroll"]);
}
const index_taro = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export {
index_taro as default
};