UNPKG

choo-taro-ui-vue3

Version:

Taro UI Rewritten in Vue 3.0

190 lines (182 loc) 7.46 kB
import { defineComponent, ref, computed, watch, onMounted, toRefs, renderSlot, resolveComponent, withCtx, openBlock, createBlock, createCommentVNode, renderList, Fragment, createElementBlock, normalizeStyle, createVNode, mergeProps } from 'vue'; import { convertToUnit } from '../utils'; import { dimensionsFactory } from '../composables'; const { useDimensions, makeDimensionsProps } = dimensionsFactory(); const AtVirtualScroll = defineComponent({ name: "AtVirtualScroll", emits: ["reach-top", "reach-bottom"], props: { ...makeDimensionsProps(), bench: { type: [Number, String], default: 0 }, itemHeight: { type: [Number, String], required: true }, items: { type: Array, default: () => [] }, scrollToItem: [Number, String], reachTopThreshold: { type: [Number, String], default: 50 }, reachBottomThreshold: { type: [Number, String], default: 50 } }, setup(props) { const first = ref(0); const last = ref(0); const scrollTop = ref(0); const elRef = ref(null); const anchor = computed(() => process.env.TARO_ENV === "h5" ? { scrollTop: scrollTop.value } : { scrollIntoView: `item-${props.scrollToItem || 0}` }); const __bench = computed(() => { return parseInt(`${props.bench}`, 10); }); const item_height = computed(() => { return parseInt(`${props.itemHeight}`, 10); }); const firstToRender = computed(() => { return Math.max(0, first.value - __bench.value); }); const lastToRender = computed(() => { return Math.min(props.items.length, last.value + __bench.value); }); const scrollContainerStyle = computed(() => ({ height: convertToUnit(props.items.length * item_height.value) })); const genScrollItemStyle = computed(() => (i) => ({ top: convertToUnit((i + firstToRender.value) * item_height.value) })); const { dimensions } = useDimensions(props); watch(() => props.height, updateFirstAndLast); watch(() => props.itemHeight, updateFirstAndLast); watch(() => props.scrollToItem, (index, _prevIndex) => { let parsedIndex = parseInt(`${index || 0}`, 10); parsedIndex = Math.min(props.items.length - 1, Math.max(0, parsedIndex)); scrollTop.value = parsedIndex * item_height.value; updateFirstAndLast(); }); onMounted(() => { if (typeof props.scrollToItem !== "undefined") { let parsedIndex = parseInt(`${props.scrollToItem}`, 10); scrollTop.value = parsedIndex * item_height.value; updateFirstAndLast(); } else { last.value = getLast(0); } }); function getFirst() { return Math.floor(scrollTop.value / item_height.value); } function getLast(first2) { const height = parseInt(`${props.height}`, 10) || elRef.value.$el.clientHeight; return first2 + Math.ceil(height / item_height.value); } function updateFirstAndLast() { first.value = getFirst(); last.value = getLast(first.value); } function handleScroll(e) { scrollTop.value = process.env.TARO_ENV === "h5" ? elRef.value.$el.scrollTop : e.detail.scrollTop; updateFirstAndLast(); } return { ...toRefs(props), anchor, elRef, scrollTop, dimensions, item_height, lastToRender, firstToRender, genScrollItemStyle, scrollContainerStyle, handleScroll }; } }); // Binding optimization for webpack code-split const _renderSlot = renderSlot, _resolveComponent = resolveComponent, _withCtx = withCtx, _openBlock = openBlock, _createBlock = createBlock, _createCommentVNode = createCommentVNode, _renderList = renderList, _Fragment = Fragment, _createElementBlock = createElementBlock, _normalizeStyle = normalizeStyle, _createVNode = createVNode, _mergeProps = mergeProps; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_taro_view = process.env.TARO_ENV === "h5" ? _resolveComponent("taro-view") : "view"; const _component_taro_scroll_view = process.env.TARO_ENV === "h5" ? _resolveComponent("taro-scroll-view") : "scroll-view"; return (_openBlock(), _createBlock(_component_taro_view, null, { default: _withCtx(() => [ ('header' in _ctx.$slots) ? (_openBlock(), _createBlock(_component_taro_view, { key: 0, class: "at-virtual-scroll__header" }, { default: _withCtx(() => [ _renderSlot(_ctx.$slots, "header") ]), _: 3 /* FORWARDED */ })) : _createCommentVNode("v-if", true), _createVNode(_component_taro_scroll_view, _mergeProps({ class: "at-virtual-scroll" }, _ctx.anchor, { ref: el => _ctx.elRef = el, style: _ctx.dimensions.style, "scroll-y": true, "scroll-with-animation": true, "upper-threshold": parseInt(`${_ctx.reachTopThreshold}`, 10), "lower-threshold": parseInt(`${_ctx.reachBottomThreshold}`, 10), onScroll: _ctx.handleScroll, onScrolltoupper: _cache[0] || (_cache[0] = $event => (_ctx.$emit('reach-top', $event))), onScrolltolower: _cache[1] || (_cache[1] = $event => (_ctx.$emit('reach-bottom', $event))) }), { default: _withCtx(() => [ _createVNode(_component_taro_view, null, { default: _withCtx(() => [ _createVNode(_component_taro_view, { class: "at-virtual-scroll__container", style: _normalizeStyle(_ctx.scrollContainerStyle) }, { default: _withCtx(() => [ (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.items.slice(_ctx.firstToRender, _ctx.lastToRender), (item, index) => { return (_openBlock(), _createBlock(_component_taro_view, { class: "at-virtual-scroll__item", key: _ctx.firstToRender + index, id: `item-${_ctx.firstToRender + index}`, style: _normalizeStyle(_ctx.genScrollItemStyle(index)) }, { default: _withCtx(() => [ _renderSlot(_ctx.$slots, "default", { index: _ctx.firstToRender + index, item: item }) ]), _: 2 /* DYNAMIC */ }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["id", "style"])) }), 128 /* KEYED_FRAGMENT */)) ]), _: 3 /* FORWARDED */ }, 8 /* PROPS */, ["style"]), ('footer' in _ctx.$slots) ? (_openBlock(), _createBlock(_component_taro_view, { key: 0, class: "at-virtual-scroll__footer" }, { default: _withCtx(() => [ _renderSlot(_ctx.$slots, "footer") ]), _: 3 /* FORWARDED */ })) : _createCommentVNode("v-if", true) ]), _: 3 /* FORWARDED */ }) ]), _: 3 /* FORWARDED */ }, 16 /* FULL_PROPS */, ["style", "upper-threshold", "lower-threshold", "onScroll"]) ]), _: 3 /* FORWARDED */ })) } AtVirtualScroll.render = _sfc_render; export default AtVirtualScroll;