uniapp table scroll-view滚动选中菜单,点击滚动指定位置
·
template
<scroll-view scroll-y class="supp-scroll right-scroll-view" :scroll-into-view="toViewId"
scroll-with-animation="true" @scroll="handleScroll">
<view v-for="(item,index) in 100" :key="item">
<view class="name-sj" :id="'item'+index">商家报价</view>
</view>
</scroll-view>
js
// 滚动位置
const toViewId = ref<string>('item0')
// 滚动到顶部
const topScroll = ref<string>('')
// 当前可见的 id
const currentVisibleId = ref<string>('')
// 存储每个元素的位置信息
const itemPositions = ref<{}>({})
// 点击左边数据重新请求自动置顶
const upReste = async ()=>{
await nextTick()
setTimeout(async () => {
toViewId.value = 'topScroll'
const positions = await getItemPositions()
itemPositions.value = positions
// 修改:获取位置后触发第一个区域
if (Object.keys(positions).length > 0) {
const sorted = Object.keys(positions).sort((a, b) => positions[a].top - positions[b].top)
const firstId = sorted[0]
if (currentVisibleId.value !== firstId) {
handleReachArea(firstId)
}
}
}, 300)
}
// ---------- 业务逻辑(到达某个区域时触发) ----------
const handleReachArea = (id) => {
// 记录当前滚动的item
currentVisibleId.value = id
// 赋值当前左边的滚动选择选项
childIndex.value = getTrailingNumber(id) ? Number(getTrailingNumber(id)) : 0
}
// ---------- 获取每个元素的位置信息 ----------
// props.processingObject 是数据一共多少条
const instance = getCurrentInstance();
const getItemPositions = () => {
return new Promise((resolve) => {
if (!instance) {
console.error('组件实例不存在');
resolve({});
return;
}
const positions = {};
const query = uni.createSelectorQuery().in(instance);
let completed = 0;
props.processingObject.forEach((id, index) => {
query.select(`#item${index}`).boundingClientRect((rect) => {
if (rect) {
positions[`item${index}`] = rect;
} else {
console.warn(`未找到元素 #${index}`);
}
completed++;
if (completed === props.processingObject.length) {
// 修改:使用独立类名查询右侧 scroll-view
const scrollQuery = uni.createSelectorQuery().in(instance);
scrollQuery.select('.right-scroll-view').boundingClientRect((scrollRect) => {
if (!scrollRect) {
resolve({});
return;
}
const result = {};
props.processingObject.forEach((id, index) => {
const rect = positions[`item${index}`];
if (rect) {
result[`item${index}`] = {
top: rect.top - scrollRect.top,
height: rect.height
};
}
});
resolve(result);
}).exec();
}
}).exec();
});
});
}
// ---------- 滚动事件处理(重写:增加顶部/底部边界) ----------
const handleScroll = (e) => {
const scrollTop = e.detail.scrollTop;
const positions = itemPositions.value;
const ids = Object.keys(positions);
if (ids.length === 0) return;
// 按 top 排序
const sorted = ids.slice().sort((a, b) => positions[a].top - positions[b].top);
const firstId = sorted[0];
const lastId = sorted[sorted.length - 1];
const firstTop = positions[firstId].top;
const lastBottom = positions[lastId].top + positions[lastId].height;
let visibleId = '';
if (scrollTop < firstTop) {
// 滚动到顶部:第一个区域可见
visibleId = firstId;
} else if (scrollTop >= lastBottom) {
// 滚动到底部:最后一个区域可见
visibleId = lastId;
} else {
// 正常区间判断
for (let id of sorted) {
const { top, height } = positions[id];
if (scrollTop >= top && scrollTop < top + height) {
visibleId = id;
break;
}
}
// 若落在间隙(极少情况),取下一个区域
if (!visibleId) {
for (let i = 0; i < sorted.length; i++) {
const id = sorted[i];
if (scrollTop < positions[id].top) {
visibleId = id;
break;
}
}
if (!visibleId) visibleId = lastId;
}
}
if (visibleId && currentVisibleId.value !== visibleId) {
handleReachArea(visibleId);
}
}
// ---------- 监听 processingObject 变化,更新位置 ----------
watch(() => props.processingObject, async (newVal) => {
if (newVal && newVal.length > 0) {
await nextTick();
setTimeout(async () => {
const positions = await getItemPositions();
itemPositions.value = positions;
if (Object.keys(positions).length > 0) {
const sorted = Object.keys(positions).sort((a, b) => positions[a].top - positions[b].top);
const firstId = sorted[0];
if (currentVisibleId.value !== firstId) {
handleReachArea(firstId);
}
}
}, 300);
}
}, { immediate: true, deep: false });
// 判断滚动选中
function getTrailingNumber(str) {
let num = '';
for (let i = str.length - 1; i >= 0; i--) {
const char = str[i];
if (char >= '0' && char <= '9') {
num = char + num;
} else {
break;
}
}
return num;
}
更多推荐
所有评论(0)