<template>
<div class="scroll-wrapper" ref="scroll">
<slot></slot>
</div>
</template>
<script setup lang="ts">
import BScrolls from "@better-scroll/core";
import { ref, onMounted, onUnmounted, watch, defineExpose } from "vue";
const props = defineProps({
list: {
type: Array,
default: () => [],
},
scrollbar: {
type: Boolean,
default: false,
},
pullUp: {
type: Boolean,
default: false,
},
scrollX: {
type: Boolean,
default: false,
},
scrollY: {
type: Boolean,
default: false,
},
enabled: {
type: Boolean,
default: false,
},
beforeScroll: {
type: Boolean,
default: false,
},
probeType: {
type: Number,
default: 0,
},
refreshDelay: {
type: Number,
default: 20,
},
scrollToEndLimit: {
type: Number,
default: 50,
},
listenScroll: {
type: Boolean,
default: false,
},
bounce: {
type: Boolean,
default: true,
},
stopPropagation: {
type: Boolean,
default: true,
},
refreshStatus: {
type: Boolean,
default: true,
},
});
interface Props {
list: Array<any>;
scrollbar: boolean;
pullUp: boolean;
scrollX: boolean;
scrollY: boolean;
enabled: boolean;
beforeScroll: boolean;
probeType: number;
refreshDelay: number;
scrollToEndLimit: number;
listenScroll: boolean;
bounce: boolean;
stopPropagation: boolean;
refreshStatus: boolean;
}
const emit = defineEmits(["scroll", "scrollToEnd", "beforeScroll"]);
let scroll = ref(null);
type bscorllType = {
scrollTo: any;
on: any;
refresh: any;
scrollToElement: any;
stop: any;
enable: any;
disable: any;
destroy: any;
y: any;
maxScrollY: any;
} | null;
let BScroll = ref<bscorllType>(null);
function initScroll() {
if (!scroll.value) {
return;
}
BScroll.value = new BScrolls(scroll.value, {
click: true,
disableMouse: false,
disableTouch: false,
scrollX: props.scrollX,
scrollY: props.scrollY,
probeType: props.probeType,
scrollbar: props.scrollbar,
bounce: props.bounce,
stopPropagation: props.stopPropagation,
enabled: props.enabled,
// mouseWheel: true,
// disableMouse: true,
// disableTouch: true,
});
BScroll.value.scrollTo(0, 0, 800);
console.log("BScroll.value", BScroll.value, props.enabled);
if (props.listenScroll) {
BScroll.value.on("scroll", scrollHandler);
}
if (props.pullUp) {
BScroll.value.on("scrollEnd", scrollToEndHandler);
}
if (props.beforeScroll) {
BScroll.value.on("beforeScrollStart", beforeScrollHandler);
}
BScroll.value.on("scrollEnd", scrollToEnd);
}
function refresh() {
BScroll.value && BScroll.value.refresh();
}
function scrollTo(a: any, b: any) {
console.log(a, b);
BScroll.value && BScroll.value.scrollTo.apply(BScroll.value, arguments);
}
function scrollToElement() {
BScroll.value &&
BScroll.value.scrollToElement.apply(BScroll.value, arguments);
}
//立即停止当前运行的滚动动画
function stop() {
BScroll.value && BScroll.value.stop();
}
//允许滚动
function enable() {
BScroll.value && BScroll.value.enable();
}
//禁止滚动
function disable() {
BScroll.value && BScroll.value.disable();
}
function destroy() {
BScroll.value && BScroll.value.destroy();
BScroll.value = null;
}
function scrollHandler(pos: any) {
emit("scroll", pos);
}
function scrollToEndHandler() {
if (
BScroll.value &&
BScroll.value.y <= BScroll.value.maxScrollY + props.scrollToEndLimit
) {
emit("scrollToEnd");
}
}
function beforeScrollHandler() {
emit("beforeScroll");
}
function scrollToEnd() {
// context.$emit("scrollEnd", position);
}
defineExpose({ refresh, scrollTo, destroy });
// function scrollToEnd(position) {
// context.$emit("scrollEnd", position);
// }
onMounted(() => {
setTimeout(() => {
initScroll();
}, props.refreshDelay);
});
onUnmounted(() => {
destroy();
});
watch(
props.list,
(newValue, oldValue) => {
// console.log("watch list", newValue, oldValue);
setTimeout(() => {
if (props.refreshStatus) {
scrollTo(0, 0);
refresh();
}
}, props.refreshDelay);
},
{ immediate: true, deep: true }
);
// return {
// scroll,
// BScroll,
// initScroll,
// refresh,
// scrollTo,
// scrollToElement,
// stop,
// enable,
// disable,
// destroy,
// scrollHandler,
// scrollToEndHandler,
// beforeScrollHandler,
// scrollToEnd,
// };
// },
// };
</script>
<style>
.scroll-wrapper {
position: relative;
}
</style>
单个页面组件内使用
<ScrollView
:listenScroll="true"
class="scrollView"
style="height: 720px; overflow: hidden"
:refreshDelay="500"
ref="shopListRef"
:scrollY="true"
>
<div class="storeyList">
<div
v-for="(item, index) in modifyCardList"
:key="index"
class="listItem"
@click="checkShopDetail(item)"
>
<div class="listContent">
<img
v-show="item && item.logoUrl"
class="itemImg"
:src="item.logoUrl ? 'static/offline' + item.logoUrl : ''"
alt=""
/>
<!-- <div class="listHeadTitle">花珑珠 赚珑珠</div> :src="item.logoUrl ? 'static/offline' + item.logoUrl : ''" -->
</div>
<div class="listFont">
<div class="fontLeft">{{ item.name }}</div>
<div class="iconExplain">
<img src="../assets/images/clothes.png" alt="" class="itemImg" />
<!-- <img
v-show="item && item.logoUrl"
class="itemImg"
:src="'static/offline' + item.logoUrl"
alt=""
/> -->
<span style="font-size: 12px; color: #888888">{{
item.floorName
}}</span>
</div>
</div>
</div>
</div>
</ScrollView>
上面是竖向滑动,比较简单,如果是横向滑动的话,尽量不要用flex布局,会互相影响,可能起不到横向滑动的作用
另外要注意:
当这些滑动的数据需要进行筛选,重新显示的时候,为了观感,每次筛选之后都要位于数据最顶部,且往下滑不会没有限制,需要进行下面的操作
setTimeout(() => {
shopListRef.value.scrollTo(0, 0);
shopListRef.value.refresh();
}, 200);
例子如下